Как найти и заменить определенные слова в текстовом файле с помощью командной строки?
sed -i 's/original/new/g' file.txt
Объяснение:
sed
= Потоковый редактор-i
= оперативный (т.е. сохраняют назад в исходный файл),Командная строка:
s
= команда заменыoriginal
= регулярное выражение, описывающее слово для замены (или просто само слово)new
= текст для замены егоg
= глобальный (т.е. замена все и не только первое вхождение)file.txt
= имя файла
Есть несколько способов сделать это. Один использует sed
и Regex. SED - это потоковый редактор для фильтрации и преобразования текста. Один пример выглядит следующим образом:
marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog
Другой способ, который может иметь больше смысла, чем < strin
и > strout
, с трубами!
Можно использовать Vim в режиме Ex:
ex -s -c '%s/OLD/NEW/g|x' file
%
выберите все строки
s
замена
g
замените все экземпляры в каждой строке
x
запишите, были ли изменения внесены (они имеют), и выход
sed
- это s tream ed itor , в котором вы можете использовать |
(pipe) для отправки стандартных потоков [ 1125] (в частности, STDIN и STDOUT) через sed
и программно изменять их на лету, что делает его удобным инструментом в философской традиции Unix; но также можете редактировать файлы напрямую, используя параметр -i
, упомянутый ниже.
Рассмотрим следующее :
sed -i -e 's/few/asd/g' hello.txt
s/
используется для s заменить найденное выражение few
на asd
:
Немногие, смелые.
Asd, смелый.
blockquote>
/g
означает «глобальный», что означает сделать это для всей строки. Если вы выключите/g
(сs/few/asd/
, всегда должно быть три слэша, несмотря ни на что), иfew
появится дважды в одной строке, только первыйfew
будет изменен наasd
: [ 1131]Немногие мужчины, немногие женщины, смелые.
Asd мужчины, немногие женщины, смелые.
blockquote>Это полезно в некоторых обстоятельствах, таких как изменение специальных символов в начале строк (например, замена символов «больше», которые некоторые люди используют для цитирования предыдущего материала в темах электронной почты, с горизонтальной табуляцией, оставляя процитировал алгебраическое неравенство позже в строке нетронутым), но в вашем примере, где вы указываете, что где-нибудь
few
должно быть заменено, убедитесь, что у вас есть/g
.Следующие две опции (флаги) объединены в одну,
-ie
:
-i
опция используется для редактирования i n места в файлеhello.txt
. [ 1136] Опция
-e
указывает команду e xpression / команду для запуска, в данном случаеs/
.Примечание. Важно использовать
-i -e
для поиска / замены. Если вы сделаете-ie
, вы создадите резервную копию каждого файла с добавленной буквой 'e'.
С помощью команды awk gsub,
awk '{gsub(/pattern/,"replacement")}' file
Пример:
awk '{gsub(/1/,"0");}' file
В приведенном выше примере все 1 заменяются на 0 независимо от столбца где он находится.
Если вы хотите выполнить замену в определенном столбце, выполните следующие действия:
awk '{gsub(/pattern/,"replacement",column_number)}' file
Пример:
awk '{gsub(/1/,"0",$1);}' file
Он заменяет 1 с 0 только в столбце 1.
Через Perl,
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Существует множество способов достигнуть его. В зависимости от сложности того, чего каждый пытается достигнуть со строковой заменой, и в зависимости от инструментов, с которыми пользователь знаком, некоторые методы могут быть предпочтены больше, чем другие.
В этом ответе я использую простой input.txt
файл, который можно использовать для тестирования всех примеров, обеспеченных здесь. Содержание файла:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Bash действительно не предназначен для обработки текста, но простые замены могут быть сделаны через расширение параметра, в особенности здесь мы можем использовать простую структуру ${parameter/old_string/new_string}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
Этот маленький сценарий не делает оперативной замены, означая, что необходимо было бы сохранить новый текст в новый файл и избавиться от старого файла, или mv new.txt old.txt
Примечание стороны: если Вам любопытно на предмет почему while IFS= read -r ; do ... done < input.txt
используется, это - в основном способ оболочки считать файл линию за линией. Посмотрите это для ссылки.
AWK, будучи утилитой обработки текста, довольно подходит для такой задачи. Это может сделать простые замены и намного более усовершенствованные на основе регулярных выражений. Это обеспечивает две функции: sub()
и gsub()
. Первый только заменяет только первое вхождение, в то время как второе - заменяет случаи в целой строке. Например, если у нас есть строка one potato two potato
, это было бы результатом:
$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana
$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'
one banana two potato
AWK может взять входной файл в качестве аргумента, таким образом делая то же самое с input.txt
, было бы легко:
awk '{sub(/blue/,"azure")}1' input.txt
В зависимости от версии AWK Вы имеете, это может или не может иметь в распоряжении редактирование, следовательно обычная практика является сохранением, и замените новый текст. Например, что-то вроде этого:
awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed является строчным редактором. Это также использует регулярные выражения, но для простых замен достаточно сделать:
sed 's/blue/azure/' input.txt
То, что хорошо об этом инструменте, - то, что он имеет в распоряжении редактирование, с которым можно включить -i
флаг.
Perl является другим инструментом, который часто используется для обработки текста, но это - язык общего назначения и используется в сетях, системном администрировании, настольных приложениях и многих других местах. Это одолжило много понятий/функций с других языков, таких как C, sed, awk, и другие. Простая замена может быть сделана как так:
perl -pe 's/blue/azure/' input.txt
Как sed, жемчуг также имеет флаг-i.
Этот язык очень универсален и также используется в большом разнообразии приложений. Это имеет много функций для работы со строками, среди которых replace()
, таким образом, если у Вас есть переменная как var="Hello World"
, Вы могли сделать var.replace("Hello","Good Morning")
Простой способ считать файл и строку замены в нем был бы как так:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
С Python, однако, также необходимо произвести в новый файл, который можно также сделать из самого сценария. Например, вот простой:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=tempfile.mkstemp()
with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
for line in fd1:
line = line.replace('blue','azure')
fd2.write(line)
os.rename(tmp[1],sys.argv[1])
С этим сценарием нужно назвать input.txt
как параметр командной строки. Точная команда для запущения скрипта Python с параметром командной строки была бы
$ ./myscript.py input.txt
или
$ python ./myscript.py input.txt
Конечно, удостоверьтесь это ./myscript.py
находится в Вашем текущем рабочем каталоге и для первого пути, удостоверьтесь, что он установлен исполняемый файл с chmod +x ./myscript.py
Python может также иметь регулярные выражения, в частности, существует re
модуль, который имеет re.sub()
функция, которая может использоваться для более усовершенствованных замен.
Вы можете сделать так:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Примеры: заменить все вхождения [logdir ',' '] (без []) на [logdir', os.getcwd ()] во всех файлах которые являются результатом команды locate, выполните:
ex1:
locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"
ex2:
locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"
где [tenorboard / program.py] - файл для поиска [ 117]