Вот, в произвольном порядке, пара решений для рассмотрения.
Перед использованием я рекомендую создать резервную копию любого файла .txt
, с которым вы собираетесь их попробовать. Эти сценарии могут привести к потере ценных данных, если их не использовать осторожно.
Если у вас есть какие-либо вопросы относительно назначения правильного пути к файлу либо;
- Переменная
txtFilePath
в Решение A - Свойство
txtFilePath
в Решение B
затем замените одну из этих строк следующим. Это позволит вам выбрать файл .
set txtFilePath to (choose file)
Решение A: Оболочка из AppleScript и использование SED (Stream EDitor)
on removeMatchingLinesFromFile(findStr, filePath)
set findStr to do shell script "sed 's/[^^]/[&]/g; s/\\^/\\\\^/g' <<<" & quoted form of findStr
do shell script "sed -i '' '/^" & findStr & "$/d' " & quoted form of (POSIX path of filePath)
end removeMatchingLinesFromFile
set txtFilePath to "Macintosh HD - Data:Users:crelle:Desktop:TestDelta.txt"
set lineOfTextToDelete to "The quick brown fox jumps over the lazy dog."
removeMatchingLinesFromFile(lineOfTextToDelete, txtFilePath)
Объяснение:
Произвольно названное removeMatchingLinesFromFile
подпрограмма / функция содержит задачи, необходимые для удовлетворения ваших требований. В нем перечислены два параметра; findStr
и filePath
. В его теле мы "выкладываем" дважды до sh
, используя команду AppleScript do shell script
.
Давайте разберемся, что здесь происходит более подробно:
Первая строка, которая читает;
set findStr to do shell script "sed 's/[^^]/[&]/g; s/\\^/\\\\^/g' <<<" & quoted form of findStr
выполняет команду sed
. Цель этой команды - избежать любых потенциальных метасимволов Basi c Regular Expression (BRE) , которые могут существовать в данной строке текста, который мы хотим удалить. Абсолютно он гарантирует, что каждый символ в данной строке будет рассматриваться как литерал при использовании в последующей команде sed
, что сводит на нет любое «специальное значение» , которое имеет метасимвол.
См. этот ответ для дальнейшего объяснения. По сути, он выполняет следующие действия:
- Каждый символ, кроме
^
, помещается в собственный набор символов [...]
выражение, чтобы рассматривать его как литерал. - Обратите внимание, что
^
- это один символ. Вы не можете представлять как [^]
, потому что оно имеет особое значение в этом месте (отрицание).
- Затем
^
символов. экранируются как \^
. - Обратите внимание, что вы не можете просто избежать каждого символа, поставив перед ним
\
, потому что это может превратить буквенный символ в мета-символ, например, \<
и \b
являются границами слов в некоторых инструментах, \n
- это новая строка, \{
- начало интервала RE, например \{1,3\}
, et c.
Кредит для этого шаблона SED идет в Эд Мортон и mklement0 .
Итак, учитывая, что строка присвоена переменной с именем lineOfTextToDelete
is:
The quick brown fox jumps over the lazy dog.
в действительности мы назначаем следующую строку переменной findStr
после ее анализа с помощью команды sed
:
[T][h][e][ ][q][u][i][c][k][ ][b][r][o][w][n][ ][f][o][x][ ][j][u][m][p][s][ ][o][v][e][r][ ][t][h][e][ ][l][a][z][y][ ][d][o][g][.]
Как вы можете видеть, что каждый символ заключен в открывающие и закрывающие квадратные скобки, то есть []
, чтобы сформировать серию скобочных выражений .
Для дальнейшей демонстрации происходящего; запустите приложение Terminal и выполните следующую составную команду:
sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"The quick brown fox jumps over the lazy dog."
Примечание При запуске вышеупомянутой составной команды непосредственно через Terminal шаблон sed
содержит меньше обратных косых черт (\
) по сравнению с шаблоном, указанным в AppleScript. Это связано с тем, что для строк AppleScript требуется экранирование любой обратной косой черты sh с дополнительной обратной косой чертой sh.
чтение второй строки
do shell script "sed -i '' '/^" & findStr & "$/d' " & quoted form of (POSIX path of filePath)
выполняет другую команду sed
через оболочку. Это выполняет задачу поиска всех экземпляров данной строки текста в файле и удаляет его / их.
Опция -i
указывает, что файл должен редактироваться на месте и требует использования следующего пустого строкового аргумента (''
) при использовании BSD версии sed
, поставляемой с macOS.
Часть '/^" & findStr & "$/d'
- это шаблон, который мы предоставляем sed
.
Метасимвол ^
совпадает со строкой null в начале пространства шаблонов - это по сути означает начало соответствия последующему шаблону регулярных выражений, только если он существует в начале строки.
Переменная Applescript findStr
- это результат, который мы получили с помощью предыдущей команды sed
. Он объединяется с предыдущей частью шаблона с помощью оператора &
.
Метасимвол $
относится к концу пространства шаблона, то есть к концу
d
- это команда удаления.
В части & quoted form of (POSIX path of filePath)
используется AppleScript POSIX path
свойство для преобразования указанного вами пути HFS , то есть
Macintosh HD - Data:Users:crelle:Desktop:TestDelta.txt
в следующий стиль POSIX путь:
/Macintosh HD - Data/Users/crelle/Desktop/TestDelta.txt
Свойство quoted form
обеспечивает правильное цитирование пути в стиле POSIX *1209*. Например, он гарантирует, что любые пробельные символы в указанном пути правильно интерпретируются оболочкой.
Опять же, чтобы дополнительно продемонстрировать, что происходит; запустите приложение Terminal и выполните следующую составную команду:
sed -i '' '/^[T][h][e][ ][q][u][i][c][k][ ][b][r][o][w][n][ ][f][o][x][ ][j][u][m][p][s][ ][o][v][e][r][ ][t][h][e][ ][l][a][z][y][ ][d][o][g][.]$/d' ~/Desktop/TestDelta.txt
Давайте разберемся, как использовать вышеупомянутую функцию removeMatchingLinesFromFile
:
Сначала мы назначим тот же путь HFS, который вы указали в своем вопросе, переменной с произвольным именем txtFilePath
:
set txtFilePath to "Macintosh HD - Data:Users:crelle:Desktop:TestDelta.txt"
Далее мы присваиваем строку текста, которую мы хотим найти и удалить, переменной с произвольным именем lineOfTextToDelete
:
set lineOfTextToDelete to "The quick brown fox jumps over the lazy dog."
Наконец мы вызываем пользовательскую функцию removeMatchingLinesFromFile
, передавая два обязательные аргументы а именно; lineOfTextToDelete
и txtFilePath
:
removeMatchingLinesFromFile(lineOfTextToDelete, txtFilePath)
Решение B: Использование ванильного AppleScript без SED:
Это решение предоставлено ниже не используются ни оболочка, ни SED, но и тот же желаемый результат, что и для Решение A .
property lineOfTextToDelete : "The quick brown fox jumps over the lazy dog."
property txtFilePath : alias "Macintosh HD - Data:Users:crelle:Desktop:TestDelta.txt"
removeMatchingLinesFromFile(lineOfTextToDelete, txtFilePath)
on removeMatchingLinesFromFile(findStr, filePath)
set paraList to {}
repeat with aLine in getLinesFromFile(filePath)
if contents of aLine is not findStr then set paraList to paraList & aLine
end repeat
set newContent to transformListToText(paraList, "\n")
replaceFileContents(newContent, filePath)
end removeMatchingLinesFromFile
on getLinesFromFile(filePath)
if (get eof of filePath) is 0 then return {}
try
set paraList to paragraphs of (read filePath)
on error errorMssg number errorNumber
error errorMssg & errorNumber & ": " & POSIX path of filePath
end try
return paraList
end getLinesFromFile
on transformListToText(ListOfStrings, delimiter)
set {tids, text item delimiters} to {text item delimiters, delimiter}
set content to ListOfStrings as string
set text item delimiters to tids
return content
end transformListToText
on replaceFileContents(content, filePath)
try
set readableFile to open for access filePath with write permission
set eof of readableFile to 0
write content to readableFile starting at eof
close access readableFile
return true
on error errorMssg number errorNumber
try
close access filePath
end try
error errorMssg & errorNumber & ": " & POSIX path of filePath
end try
end replaceFileContents
Объяснение:
Я оставлю это объяснение Короче говоря, сам код , вероятно, проще для понимания, чем Решение A .
Подпрограмма removeMatchingLinesFromFile
, по существу, выполняет следующее с помощью дополнительных вспомогательных функций:
read
- содержимое данного файла .txt
с помощью функции getLinesFromFile
и return
sa список . Каждый элемент в возвращенном списке содержит каждую строку / абзац текста, найденного в содержимом файла .txt
.
Затем мы пропускаем oop через каждый элемент (т.е. каждую строку текста) через оператор repeat
. Если contents
каждого элемента не не совпадает с заданной строкой текста, мы находим ее в другом списке, то есть в списке, назначенном переменной paraList
.
Затем список, назначенный переменной paraList
, передается в функцию transformListToText
вместе с разделителем новой строки (\n
). Функция transformListToText
возвращает новую строку.
Наконец, с помощью функции replaceFileContents
мы open for access
исходный файл .txt
и более write
его содержимое с новым содержимым.
Важное примечание, применимое к любому решению: При указании строка текста, которую вы хотите удалить (т. е. строка, назначенная переменной lineOfTextToDelete
), гарантирует, что все и вся backsla sh \
, которые вы можете найти, экранированы с другим. Например; если строка, которую вы хотите найти, содержит единственную обратную косую черту sh \
, тогда экранируйте ее, чтобы стать двумя \\
. Точно так же, если строка, которую вы хотите найти, содержит две последовательные обратные косые черты \\
, тогда экранируйте каждую из них, чтобы стать четырьмя \\\\
и т. Д.