Интерпретировать как фиксированную строку / литерал, а не как регулярное выражение, используя sed - PullRequest
30 голосов
/ 09 ноября 2010

Для grep есть опция фиксированной строки, -F (fgrep), чтобы отключить регулярное выражение строки поиска. Есть ли подобное оборудование для sed? Я не мог найти ничего в этом человеке. Рекомендация другого инструмента GNU / Linux также подойдет.

Я использую sed для поиска и замены: sed -i "s/abc/def/g"

Ответы [ 6 ]

7 голосов
/ 12 ноября 2010

Вы должны использовать sed? Если вы пишете скрипт bash, вы можете сделать

#!/bin/bash
pattern='abc'
replace='def'
file=/path/to/file
tmpfile="${TMPDIR:-/tmp}/$( basename "$file" ).$$"
while read -r line
do
  echo "${line//$pattern/$replace}"
done < "$file" > "$tmpfile" && mv "$tmpfile" "$file"

В более старой оболочке Bourne (например, ksh88 или POSIX sh) у вас может не быть такой крутой структуры ${var/pattern/replace}, но у вас есть ${var#pattern} и ${var%pattern}, которые можно использовать для разделения строки и затем соберите его. Если вам нужно сделать это, вы получите гораздо больше кода - но на самом деле это не так уж плохо.

Если вы еще не находитесь в сценарии оболочки, вы можете довольно легко создать параметры шаблона, замены и имени файла и просто вызвать его. :)

PS - структура $ {TMPDIR: - / tmp} использует $ TMPDIR, если это установлено в вашей среде, или использует / tmp, если переменная не установлена. Мне нравится вставлять pid текущего процесса в конец имени файла в надежде, что оно будет немного более уникальным. Вам, вероятно, следует использовать mktemp или аналогичный в «реальном мире», но для быстрого примера это нормально, а двоичный файл mktemp не всегда доступен.

5 голосов
/ 09 ноября 2010

Вариант 1) Выход из регулярных выражений. Например. sed 's/\$0\.0/0/g' заменит все вхождения $ 0.0 на 0.

Вариант 2) Используйте perl -p -e в сочетании с quotemeta. Например. perl -p -e 's/\\./,/gi' заменит все вхождения . на ,.

Вы можете использовать вариант 2 в таких сценариях:

SEARCH="C++"
REPLACE="C#"
cat $FILELIST | perl -p -e "s/\\Q$SEARCH\\E/$REPLACE/g" > $NEWLIST
2 голосов
/ 27 октября 2016

если вы не хотите экранировать свою строку,
Вы можете достичь своей цели в 2 этапа:

fgrep строка (получение белья), которую вы хотите заменить,
и затем используйте sed для замены этой строки.

, например

#/bin/sh
PATTERN='foo*[)*abc'    # we need it literal
LINENUMBER="$( fgrep -n "$PATTERN" "$FILE" | cut -d':' -f1 )"

NEWSTRING='my new string'
sed -i "${LINENUMBER}s/.*/$NEWSTRING/" "$FILE"
2 голосов
/ 04 июня 2015

Если вы не против Ruby или длинных строк, вы можете использовать это:

alias replace='ruby -e "File.write(ARGV[0], File.read(ARGV[0]).gsub(ARGV[1], ARGV[2]))"'

replace test3.txt abc def

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

0 голосов
/ 17 октября 2018

Вы можете сделать это в двух строках bash-кода, если все в порядке с чтением всего файла в память. Это довольно гибко - шаблон и замена могут содержать новые строки для соответствия между строками, если это необходимо. Он также сохраняет любой завершающий символ новой строки или его отсутствие, чего нет в простом цикле с read.

mapfile -d '' < file
printf '%s' "${MAPFILE//"$pat"/"$rep"}" > file

Для полноты, если файл может содержать нулевые байты (\0), нам нужно расширить вышеприведенное, и оно станет

mapfile -d '' < <(cat file; printf '\0')
last=${MAPFILE[-1]}; unset "MAPFILE[-1]"
printf '%s\0' "${MAPFILE[@]//"$pat"/"$rep"}" > file
printf '%s' "${last//"$pat"/"$rep"}" >> file
0 голосов
/ 14 ноября 2010

Вы должны использовать replace вместо sed.

со страницы руководства:

   The replace utility program changes strings in place in files or on the
   standard input.

   Invoke replace in one of the following ways:

       shell> replace from to [from to] ... -- file_name [file_name] ...
       shell> replace from to [from to] ... < file_name

   from represents a string to look for and to represents its replacement.
   There can be one or more pairs of strings.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...