sed -s substitute
Введение
Чтобы использовать команду sed substitute нужна опция 's'
Общий синтаксис выглядит так:
sed '[range] s/<string>/<replacement>/' file
Перевод
sed ' [диапазон] s/<строка>/<замена>/' файл
range - это область в которой нужно делать замену. Задаётся через условие. Всегда должен быть внутри / /
string - это набор символов который нужно заменить
replacement - это набор символов на который заменяется string
file - это имя файла (можно с путём до файла) в котором эта замена будет произведена
Замена слова в файле
Обычно SED применяют к файлам, например к логам или конфигам.
Предположим, что у нас есть файл
input.txt
следующего содержания
Here is a String
Here is an Integer
Here is a Float
Мы хотим заменить слово Here на There
sed 's/Here/There/' input.txt
Результат будет выведен в консоль:
There is a String
There is an Integer
There is a Float
Если нужно не вывести в консоль (в stdout) а изменить содержание файла - используем опцию -i
sed -i 's/Here/There/' input.txt
В этом случае перепишется исходный файл input.txt
Хорошей практикой считается сначала проверить свой скрипт без -i и если всё работает верно внести изменения в файл.
С помощью -i.bak можно создать резервный файл (бэкап)
Рассмотрим пример посложнее.
Пусть файл
input.txt
теперь выглядит так:
Here is an Apple. Here is a Pen. Here is an ApplePen
Integer is Here
Here is a Float
Here is a Pen. Here is a Pineapple. Here is a PineapplePen
sed 's/Here/There/' input.txt
Как Вы сейчас увидите, замена произойдёт только по одному разу в строке
There is an Apple. Here is a Pen. Here is an ApplePen
Integer is There
There is a Float
There is a Pen. Here is a Pineapple. Here is a PineapplePen
Чтобы заменить все слова нужна опция g
sed 's/Here/There/g' input.txt
There is an Apple. There is a Pen. There is an ApplePen
Integer is There
There is a Float
There is a Pen. There is a Pineapple. There is a PineapplePen
Замена слова в файле и вывод результата в другой файл
Та же замена, но с выводом в новый текстовый файл, который мы назовём output:
sed 's/Here/There/' input.txt > output.txt
Замена слова в нескольких файлах одновременно
Если нужно обработать сразу несколько файлов: например файл 1.txt с содержанием
First File: Here
И файл 2.txt с содержанием
Second File: Here
Это можно сделать используя *.txt
sed 's/Here/There/' *.txt > output.txt
На выходе файл output.txt будет выглядеть так
First File: There
Second File: There
Замена только в определённых строках
Рассмотрим файл input.txt
cat input.txt
lex red red test red muha lex red red lex red lex blue
Заменим red на yellow, но не везде, а только там где строка начинается с lex
sed -i '/^lex/ s/red/yellow/' input.txt
cat input.txt
lex yellow red test red muha lex red red lex yellow lex blue
/^lex/ - замену нужно делать только в тех строках, которые начинаются с lex - так мы задали range
g
Если не задавать range как в предыдущем примере ,то в каждой строке первый red будет заменён на yellow
sed -i 's/red/yellow/' input.txt
cat input.txt
lex yellow yellow test yellow muha lex yellow red lex yellow lex blue
Чтобы заменить вообще все red на yellow - нужно добавить опцию g (greed - жадность)
sed -i 's/red/yellow/g' input.txt
cat input.txt
lex yellow yellow test yellow muha lex yellow yellow lex yellow lex blue
Добавить отступы
Рассмотрим скрипт script.sh
nl -ba script.sh
1 #!/bin/bash 2 3 i=0 4 while [ $i -le 3 ] 5 do 6 echo "i= " 7 echo $i 8 (( i++ )) 9 done
Если вы решите добавить отступы внутри do … done : то есть отодвинуть, скажем, на четыре пробела текст в строках 6, 7 и 8 - выполните
sed -i ' 6,8 s/^/ /g' script.sh
nl -ba script.sh
1 #!/bin/bash 2 3 i=0 4 while [ $i -le 3 ] 5 do 6 echo "i= " 7 echo $i 8 (( i++ )) 9 done
Предупреждаю, что если у вас в скрипте есть пустые строки - nl их считать не будет а sed будет - поэтому я использовал nl с опциями ba
Если вносить изменения в исходный файл не нужно - можно использовать
sed -n ' 6,8 s/^/ /p' script.sh
echo "i= " echo $i (( i++ ))
Заменить пустые строки
Заменить все пустые строки на двойные тэги переноса строки
$ sed 's/^[[:space:]]*$/\<br\>\<br\>/' input.txt > output.txt
Заменить начало строки
Рассмотрим файл input.txt
cat input.txt
lex red red test red muha lex red red lex red lex blue
На начало строки указывает символ ^
Заменим red на yellow, но не везде, а только там где строка начинается с lex
sed -i '/^lex/ s/red/yellow/' input.txt
cat input.txt
lex yellow red test red muha lex red red lex yellow lex blue
Изменить значение в JSON файле
Рассмотрим файл sample.json в котором SpamBlocking нужно заменить на true по умолчанию
{ "websites": { "AppUpdateURL": "", "BlockAddons": true, "EncryptedExtensions": { "Enabled": true, "Locked": true }, "SpamBlocking": { "Default": false }, "Permissions": { "Camera": { "BlockRequests": true }, "Location": { "BlockRequests": true }, "Microphone": { "BlockRequests": true }, "Popups": { "BlockRequests": true } } } }
Если значение SpamBlocking встречается в JSON файле только один раз - подойдёт следующий скрипт j.sh
# www.eth1.ru FILENAME=sample.json PATTERN=SpamBlocking # Find line number of the PATTERN PREVLINE=$(sed -n /$PATTERN/= ./$FILENAME) # Calculate line with value LINE=$(( $PREVLINE + 1 )) # Replace sed -i $LINE's@false@true@' ./$FILENAME
./j.sh
Проверить результать можно с помощью grep
grep -A1 SpamBlocking sample.json
"SpamBlocking": { "Default": true
Работа с пробелами в путях Windows
Если нужно применить sed в
Windows
нужно учесть возможное наличие пробелов в путях.
Предположим настройки софта лежат в файлах
Studio.exe.config
,
Loader.exe.config
Tool.exe.config
в директории
C:\Program Files\My Win Software
Или если открыть через Git Bash
/c/Program Files/My Win Software
и её поддиректории net48. Строка, в которой прописан уровень логов, содержит <variable name="logLevel"
Цель - заменить уровень логов с Erorr на Debug
WD=/c/Program\ Files/My\ Win\ Software S="$WD/Studio.exe.config" L="$WD/Loader.exe.config" T="$WD/net48/Tool.exe.config" /usr/bin/sed.exe -i '/<variable name="logLevel"/ s/Error/Debug/' "$S" "$L" "$T"