sed/awk заменить определенный шаблон на другой

Использование расширения параметра оболочки

$ for f in *.log; do g="${f/#file_/}"; echo mv -- "$f" "files_${g%%_*}.log"; done
mv -- file_948_of_2000_push_data_12345.log files_948.log
mv -- file_950_of_2000_push_data_12345.log files_950.log

Использование основанного на perl prename или команды переименования

$ prename -n -- 's/^(.*?)_(.*?)_.*\.log$/$1s_$2.log/' *.log
file_948_of_2000_push_data_12345.log renamed as files_948.log
file_950_of_2000_push_data_12345.log renamed as files_950.log

Использование mmv

$ mmv -n '*_*_*.log' '#1s_#2.log'
file_948_of_2000_push_data_12345.log -> files_948.log
file_950_of_2000_push_data_12345.log -> files_950.log

Удалите -n или echo в зависимости от ситуации.

1
09.10.2016, 22:47
3 ответа

Sed может справиться с этим довольно легко. Это единственная команда «подстановки» с префиксом диапазона адресов. Я добавил дополнительный интервал для лучшей читаемости:

sed -e '/^\[ABC\]$/ , /^\[.*\]$/     s/^\(value1=\).*$/\1notbla/'

Без дополнительного интервала это:

sed -e '/^\[ABC\]$/,/^\[.*\]$/s/^\(value1=\).*$/\1notbla/'

Вам действительно не нужны привязанные регулярные выражения, но они могут быть более безопасными в некоторых случаях необычного ввода. Немного более короткая версия с незакрепленными регулярными выражениями:

sed -e '/\[ABC\]/,/^\[/s/^\(value1=\).*$/\1notbla/'

Объяснение:

Вы просили объяснить каждый флаг или параметр, и у меня есть время, так что готово. Я объясняю последнюю (самую короткую) версию из трех перечисленных выше команд Sed.

Первая часть строки - это диапазон адресов: / startregex /, / stopregex / Команда s ubstitute, которая следует за диапазоном адресов, применяется только к строкам из от startregex до stopregex (включительно).

В этом случае начальное регулярное выражение - / \ [ABC \] / . Квадратные скобки обычно являются специальными символами в регулярном выражении, поэтому мы ставим перед каждым символом обратную косую черту, чтобы обозначить буквальные символы квадратных скобок.

Регулярное выражение остановки - / ^ \ [/ , которое использует специальный символ регулярного выражения ^ для обозначения начала строки. Этот шаблон будет соответствовать любой строке, которая начинается с буквальной левой квадратной скобки ( [).

Команда s ubstitute в основном довольно проста; общий формат - s / findregex / replacetext / . Он также может иметь специальные флаги, помещенные после последнего / , чтобы изменить его поведение, но я здесь не использую никаких таких флагов.

«Найти регулярное выражение»: ^ \ (value1 = \). * $ .

Каретка ( ^ ) соответствует началу строки, как упоминалось ранее, а знак доллара ( $ ) соответствует концу строки. Таким образом, весь этот шаблон должен соответствовать всей строке, а не только ее части.

Скобки ( () ), в отличие от квадратных скобок, по умолчанию в регулярных выражениях являются не -специальными, поэтому мы помещаем перед ними обратную косую черту, чтобы придать им особое значение. Они позволяют использовать части совпадающего текста (текст, совпадающий с "регулярным выражением поиска") в заменяющем тексте. В частности, \ 1 в тексте замены означает: «Текст соответствует первому набору круглых скобок в регулярном выражении». В данном случае это всегда просто «значение1 =».

Последний элемент в «регулярном выражении поиска» - . * . Точка (. ) означает «любой отдельный символ», а звездочка ( * ) означает «любое количество раз (ноль или более)». Итак, точка-звезда (.* ) соответствует всей остальной части строки после знака равенства.

«notbla» в замещающем тексте - это просто статический текст, ничего особенного в этом нет.


Чтобы по-настоящему изучить Sed, я настоятельно рекомендую Grymoire Sed tutorial , который доступен бесплатно в Интернете.

6
27.01.2020, 23:16

другое решение awk

$ cat ip.txt 
[ABC]
value1=bla
value2=bla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla

Если строка начинается с [, назначьте флаг, который будет установлен или сброшен в зависимости от имени блока. Затем, если флаг установлен, выполните замену

$ awk '/^\[/{f=/\[ABC\]/} f{sub("value1=bla","value1=nobla")} 1' ip.txt 
[ABC]
value1=nobla
value2=bla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla


Аналогичное решение в perl , замените замену для демонстрации

$ perl -pe '$f=/\[ABC\]/ if /^\[/; s/value2=bla/value2=nobla/ if $f;' ip.txt 
[ABC]
value1=bla
value2=nobla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla


Если все справа от = должно быть изменено независимо от В частности, соответствующий bla , используйте

awk '/^\[/{f=/\[ABC\]/} f{sub(/value1=.*/,"value1=nobla")} 1' ip.txt 
perl -pe '$f=/\[ABC\]/ if /^\[/; s/value2=.*/value2=nobla/ if $f;' ip.txt
1
27.01.2020, 23:16
awk '
  BEGIN {FS=OFS="=";}
  /\[.*\]/ {if ($0 == "[ABC]") edit=1; else edit=0;}
  {if (edit && $1 == "value1" ) $2="notbla";}1
' file 
2
27.01.2020, 23:16

Теги

Похожие вопросы