Найти и заменить текст в файле с помощью команд

Ответы:

1053
sed -i 's/original/new/g' file.txt

Объяснение:

  • sed = Stream EDitor
  • -i = на месте (т.е. сохранить обратно в исходный файл)
  • Командная строка:

    • s = команда замены
    • original = регулярное выражение, описывающее слово для замены (или только само слово)
    • new = текст для замены
    • g = глобальный (т.е. заменить все, а не только первое вхождение)
  • file.txt = имя файла

cscarney
источник
3
@Akiva Если вы включите регулярные выражения, специальные символы в вашем поиске sedбудут соответствовать им. Добавьте -rфлаг, если вы хотите использовать вместо этого расширенные RE.
cscarney
32
@mcExchange Если /вам требуется сопоставить именно символ, вы можете просто использовать какой-то другой символ в качестве разделителя (например 's_old/text_new/text_g'). В противном случае вы можете поставить \ перед любым из них, $ * . [ \ ^чтобы получить буквальный символ.
Скарни
3
@BrianZ Для файловой системы вывод sed - это новый файл с тем же именем. Это одна из часто
cscarney
17
Команду OSX sed -i '.bak' 's/original/new/g' file.txtтакже можно запустить с расширением нулевой длины sed -i '' 's/original/new/g' file.txt, которое не будет создавать резервную копию.
Кирк
20
Пользователи MacOS должны будут добавить '' "после -i в качестве параметра для -i ed.gs/2016/01/26/os-x-sed-invalid-command-code, чтобы файл был перезаписан.
geoyws
32

Есть несколько разных способов сделать это. Один использует 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является с трубами!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog
Марко Чеппи
источник
6
обратите внимание, что catв cat file | sed '...'этом нет необходимости. Вы можете прямо сказать sed '...' file.
Федорки
1
На самом деле это может быть уменьшено еще больше: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarlyбудет принимать файл и делать 2 изменения на месте во время создания резервной копии. Использование time bash -c "$COMMAND"времени предполагает, что эта версия примерно в 5 раз быстрее.
pbhj
24

Есть множество способов достичь этого. В зависимости от сложности того, чего можно достичь с помощью замены строки, и в зависимости от инструментов, с которыми пользователь знаком, некоторые методы могут быть предпочтительнее других.

В этом ответе я использую простой input.txtфайл, который вы можете использовать для проверки всех примеров, представленных здесь. Содержимое файла:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BASH

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

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 - это редактор строк. Он также использует регулярные выражения, но для простых замен достаточно сделать:

sed 's/blue/azure/' input.txt

Что хорошо в этом инструменте, так это то, что он имеет редактирование на месте, которое вы можете включить с -iфлагом.

Perl

Perl - это еще один инструмент, который часто используется для обработки текста, но это язык общего назначения, который используется в сетях, системном администрировании, настольных приложениях и во многих других местах. Он заимствовал много концепций / функций из других языков, таких как C, sed, awk и другие. Простую замену можно сделать так:

perl -pe 's/blue/azure/' input.txt

Как и у sed, у perl также есть флаг -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()функцию, которую можно использовать для более сложных замен.

Сергей Колодяжный
источник
1
Хорошая подборка! Другой возможный способ, не упомянутый здесь, - использование trкоманды в Unix
Tapajit Dey
1
@TapajitDey Да, tr еще один замечательный инструмент, но учтите, что он предназначен для замены наборов символов (например, tr abc cdeбудет переводить aв c, bк d. Это немного отличается от замены целых слов как на sedилиpython
Сергей Колодяжный,
22

Вы можете использовать Vim в режиме Ex:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % выбрать все строки

  2. s замена

  3. g заменить все экземпляры в каждой строке

  4. x написать, если изменения были внесены (есть) и выйти

Стивен Пенни
источник
21

Через команду gsub в awk,

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 только в первом столбце.

Через Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Авинаш Радж
источник
Я использовал это на терминале MacOS, и он ничего не делал ...
Джим
Протестировано на Alpine Linux (в контейнере Docker) и не
получено
@ SalathielGenèse что ты пытаешься достичь?
Авинаш Радж
Я смотрю файл с inotifywaitпод shокр, и представление данных в формате CSV (поскольку пользовательский формат глючит). Затем я подумал, что нет простого способа обработки CSV-документа в сценариях оболочки ... И я хочу, чтобы он был очень легким. Поэтому я запустил довольно простой скрипт для разбора и отчета о CSV. Я прочитал спецификацию CSV и заметил, что она более сложна, чем я ожидал, и поддерживаю многострочное значение, заключенное в двойные кавычки. Я полагался на sedтокенизацию, но вскоре понял, что даже то, что sedназывается мультилиней, состоит из двух строк. Что тогда, если одно из моих значений CSV занимает более двух строк?
Salathiel Genèse
Лучше задать свою проблему как вопрос.
Авинаш Радж
8

sedявляется s Tream ред itor , в том , что вы можете использовать |(трубы) для передачи стандартных потоков (STDIN и STDOUT в частности) путем sedи изменять их программно на лету, что делает его удобным инструментом в философии традиции Unix; но также можете редактировать файлы напрямую, используя -iпараметр, указанный ниже.
Учтите следующее :

sed -i -e 's/few/asd/g' hello.txt

s/используется для S ubstitute найденное выражение fewс asd:

Немногие, смелые.


ASD, смелый.

/gрасшифровывается как «глобальный», что означает сделать это для всей строки. Если вы пропустите /gs/few/asd/, всегда должно быть три слэша, несмотря ни на что) и fewпоявятся дважды в одной строке, только первый fewизменится на asd:

Немногие мужчины, немногие женщины, смелые.


Asd мужчины, немногие женщины, смелые.

Это полезно в некоторых обстоятельствах, таких как изменение специальных символов в начале строк (например, замена символов «больше», которые некоторые люди используют для цитирования предыдущего материала в темах электронной почты, на горизонтальной табуляции, оставляя после этого цитируемое алгебраическое неравенство позже в строке нетронутый), но в вашем примере, где вы указываете, что где-либо few происходит, его следует заменить, убедитесь, что у вас есть /g.

Следующие два параметра (флаги) объединены в один -ie:

-iОпция используется для редактирования я п установить на файл hello.txt.

-eОпция указывает на электронную XPression / команду для запуска, в данном случае s/.

Примечание. Важно использовать его -i -eдля поиска / замены. Если вы это сделаете -ie, вы создадите резервную копию каждого файла с добавленной буквой «е».

Чаминда Бандара
источник
2

Вы можете сделать так:

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"

ех2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

где [tenorboard / program.py] - файл для поиска

Nguyễn Tuấn Anh
источник
Здравствуй. Ваш выбор строк ( logdir', ''-> /logdir', os.getcwd()) затрудняет анализ этого ответа. Кроме того, стоит указать, что ваш ответ сначала находит файлы для использования sed, потому что это не является частью вопроса.
mwfearnley
Привет, этот ответ - и поиск, и замена всех, если он нашел <старый текст> в файле.
Nguyấn Tuấn Anh
Я выбираю этот ответ для всех, кто использует тензорную доску в кератах, которые хотят изменить команду с: tenorboard --logdir = '/ path / to / log / folder /', чтобы использовать: только тензорную доску, при нахождении в папке журналов. это очень удобно
Nguyễn Tuấn Anh