Вы можете заменить символы, используя формулу sed s/old_string/new_string/
.
Из manpage:
sed - stream editor for filtering and transforming text
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successful, replace that portion matched with
replacement. The replacement may contain the special character & to refer to that portion of the pat‐
tern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
Если у вас есть набор символов для замены, то я рекомендую создать файл (например, replace.sed
), содержащий определение замены следующим образом:
$ cat replace.sed
s/ă/a/g
s/â/a/g
s/î/i/g
s/ș/s/g
s/ț/t/g
А затем запуск можно выполнить так:
sed -f replace.sed new.php
Который заменит символы, указанные в replace. sed
новыми из old.php
и выводятся в new.php
sed -i -f replace.sed file.php
Которые заменяют file.php
одновременно заменяя символы, указанные в replace.sed
Из manpage:
-i[SUFFIX], --in-place[=SUFFIX]
редактировать файлы на месте (делает резервную копию, если указано SUFFIX)
Или вы можете определить одновременно в строке типа:
sed -e 's/ă/a/g' -e 's/â/a/g' -e 's/î/i/g' -e 's/ș/s/g' -e 's/ț/t/g'
Для выполнения этой операции для всех .php
файлов, вы можете использовать что-то вроде:
find . -name "*.php" -exec sed -i '' -f replace.sed '{}' \;
for i in *.php; do sed -i '' -f replace.sed "$i"; done
Примечание: Используйте -maxdepth 1
с find
для ограничения поиска *.php
только в текущем каталоге. Посетите man sed
для получения дополнительной информации.
Так как соглашениеp
, похоже, отсутствует в вашей системе, обратите внимание на эту альтернативу, основанную на sed и awk, для применения grep и работы с шаблонами, считываемыми локальным файлом.
PS: Поскольку вы используете osx, я не уверен, поддерживает ли ваша версия awk указанное ниже использование.
awk
может имитировать grep с помощью операции И для нескольких шаблонов в этом случае:
awk '/ pattern1 / && / pattern2 / && / pattern3 /'
Таким образом, вы можете преобразовать файл шаблона следующим образом:
$ cat ./tmp/d1.txt
"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"
На это:
$ sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' ./tmp/d1.txt
/surveillance data/ && /surveillance technology/ && /cctv camera/
/social media/ && /surveillance techniques/ && /enforcement agencies/
/social control/ && /surveillance camera/ && /social security/
/surveillance data/ && /security guards/ && /social networking/
/surveillance mechanisms/ && /cctv surveillance/ && /contemporary surveillance/
PS: Вы можете перенаправить вывод в другой файл, используя > другой файл
в конце, или вы можете использовать параметр sed -i
, чтобы сделать изменения на месте в том же файле шаблонов условий поиска.
Затем вам просто нужно загрузить в awk шаблоны в формате awk из этого файла шаблонов:
$ while IFS= read -r line;do awk "$line" *.txt;done<./tmp/d1.txt #d1.txt = my test pattern file
Вы также не можете преобразовать шаблоны в исходном файле шаблонов, применив sed в каждой строке этого исходного файла шаблонов следующим образом:
while IFS= read -r line;do
line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line")
awk "$line" *.txt
done <./tmp/d1.txt
Или однострочно:
$ while IFS= read -r line;do line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line"); awk "$line" *.txt;done <./tmp/d1.txt
Приведенные выше команды возвращают правильные результаты И в моих тестовых файлах, которые выглядят следующим образом:
$ cat d2.txt
This guys over there have the required surveillance technology to do the job.
The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
$ cat d3.txt
All surveillance data are locked.
All surveillance data are locked and guarded by security guards.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)
Результаты:
$ while IFS= read -r line;do awk "$line" *.txt;done<./tmp/d1.txt
#or while IFS= read -r line;do line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line"); awk "$line" *.txt;done <./tmp/d1.txt
The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)
Обновление:
Вышеупомянутое решение awk выводит содержимое совпадающих файлов txt.
Если вы хотите отображать имена файлов вместо содержимого, используйте следующий awk там, где это необходимо:
awk "$line""{print FILENAME}" *.txt
Проблема немного неудобная, но вы можете подойти к ней следующим образом:
while read one two three four five six
do grep -lF "$one $two" *files* | xargs grep -lF "$three $four" | xargs grep -lF "$five $six"
done < patterns | sort -u
Это предполагает, что ваш Файл шаблона содержит ровно шесть слов в строке (три шаблона по два слова в каждом). Логические и
реализованы путем объединения трех последовательных фильтров ( grep
). Обратите внимание, что это не особенно эффективно. Решение awk
, вероятно, будет быстрее.
Это еще один подход, который, кажется, работает в моих тестах.
Я скопировал данные вашего строкового файла в файл с именем d1.txt и переместил его в отдельный каталог (т.е. tmp), чтобы в дальнейшем grep не соответствовал строковому файлу в том же файле (d1.txt).
Затем вставьте в этот файл строк (в моем случае d1.txt) точку с запятой между каждым поисковым запросом с помощью следующей команды: sed -i 's / "" / ";" / g' ./tmp /d1.txt
$ cat ./tmp/d1.txt
"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"
$ sed -i 's/" "/";"/g' ./tmp/d1.txt
$ cat ./tmp/d1.txt
"surveillance data";"surveillance technology";"cctv camera"
"social media";"surveillance techniques";"enforcement agencies"
"social control";"surveillance camera";"social security"
"surveillance data";"security guards";"social networking"
"surveillance mechanisms";"cctv surveillance";"contemporary surveillance"
Затем удалите двойные кавычки с помощью команды sed 's / "// g' ./tmp/d1.txt
PS: Это может не быть действительно необходимым, но я удалил двойные кавычки для тестирования.
$ sed -i 's/"//g' ./tmp/d1.txt && cat ./tmp/d1.txt
surveillance data;surveillance technology;cctv camera
social media;surveillance techniques;enforcement agencies
social control;surveillance camera;social security
surveillance data;security guards;social networking
surveillance mechanisms;cctv surveillance;contemporary surveillance
Нет, вы можете использовать grep для всех файлов в текущем каталоге с помощью программы agreementp
, которая разработана специально для обеспечения работы с несколькими шаблонами grep с операцией AND.
agreementp
требует, чтобы несколько шаблонов были разделены точкой с запятой ;
, чтобы их можно было вычислить как И.
В моих тестах я создал два образца файла с содержимым:
$ cat d2.txt
This guys over there have the required surveillance technology to do the job.
The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
$ cat d3.txt
All surveillance data are locked.
All surveillance data are locked and guarded by security guards.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)
Выполнение согласования в текущем каталоге возвращает правильные строки (с AND) и имена файлов:
$ while IFS= read -r line;do agrep "$line" *;done<./tmp/d1.txt
d2.txt: The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
d3.txt: There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)
Я бы использовал perl
, что-то вроде:
perl -MFile::Find -MClone=clone -lne '
# parse the strings.txt input, here looking for the sequences of
# 0 or more characters (.*?) in between two " characters
for (/"(.*?)"/g) {
# @needle is an array of associative arrays whose keys
# are the "strings" for each line.
$needle[$n]{$_} = undef;
}
$n++;
END{
sub wanted {
return unless -f; # only regular files
my $needle_clone = clone(\@needle);
if (open FILE, "<", $_) {
LINE: while (<FILE>) {
# read the file line by line
for (my $i = 0; $i < $n; $i++) {
for my $s (keys %{$needle_clone->[$i]}) {
if (index($_, $s)>=0) {
# if the string is found, we delete it from the associative
# array.
delete $needle_clone->[$i]{$s};
unless (%{$needle_clone->[$i]}) {
# if the associative array is empty, that means we have
# found all the strings for that $i, that means we can
# stop processing, and the file matches
print $File::Find::name;
last LINE;
}
}
}
}
}
close FILE;
}
}
find(\&wanted, ".")
}' /path/to/strings.txt
Это означает, что мы минимизируем количество поисков строк.
Здесь мы обрабатываем файлы построчно. Если файлы действительно достаточно маленькие, вы можете обрабатывать их как единое целое, что немного упростит его и может улучшить производительность.
Обратите внимание, что он ожидает, что файл списка будет в формате:
"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"
с числом (не обязательно 3) строк в кавычках (с двойными кавычками) в каждой строке.Строки в кавычках не могут содержать сами символы двойных кавычек. Символ двойной кавычки не является частью искомого текста. То есть, если файл списка содержит:
"A" "B"
"1" "2" "3"
, который будет сообщать путь ко всем обычным файлам в текущем каталоге и ниже, которые содержат либо
A
и B
1
, 2
и 3
где-либо в них.