Вывод перенаправления от sed 's/c/d /' myFile к myFile

Я использую sed в сценарии, чтобы сделать замену, и я хочу иметь замененную перезапись файла файл. Обычно я думаю, что Вы использовали бы это:

% sed -i 's/cat/dog/' manipulate
sed: illegal option -- i

Однако, поскольку Вы видите, что мой sed не имеет той команды.

Я попробовал это:

% sed 's/cat/dog/' manipulate > manipulate

Но это просто поворачивается, управляют в пустой файл (имеет смысл).

Это работает:

% sed 's/cat/dog/' manipulate > tmp; mv tmp manipulate

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

18
задан sixtyfootersdude 6 April 2010 в 14:13
поделиться

6 ответов

Я обычно использую 3-й способ, но с важным изменением :

$ sed 's / cat / dog /' манипулировать> tmp && mv tmp манипулировать

Т.е. измените ; на && , чтобы перемещение происходило только в случае успешного выполнения команды sed; иначе вы потеряете исходный файл, как только сделаете опечатку в синтаксисе sed.

Примечание! Для тех, кто читает заголовок и пропускает ограничение OP «мой sed не поддерживает -i » : для большинства людей sed будет поддерживать -i , поэтому лучший способ сделать это:

$ sed -i 's / cat / dog /' manage

37
ответ дан 30 November 2019 в 06:09
поделиться

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

ed file.txt <<EOF
%s/cat/dog/
wq
EOF
6
ответ дан 30 November 2019 в 06:09
поделиться

Керниган и Пайк в Искусство программирования Unix обсуждают этот вопрос. Их решение - написать сценарий под названием overwrite , который позволяет делать такие вещи.

Использование: перезаписать файл cmd файл .

# overwrite: copy standard input to output after EOF

opath=$PATH
PATH=/bin:/usr/bin

case $# in
0|1)   echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
esac

file=$1; shift
new=/tmp/overwr1.$$; old=/tmp/overwr2.$$
trap 'rm -f $new $old; exit 1' 1 2 15  # clean up

if PATH=$opath "$@" >$new
then
       cp $file $old           # save original
       trap '' 1 2 15          # wr are commmitted
       cp $new $file
else
       echo "overwrite: $1 failed, $file unchanged" 1>&2
       exit 1
fi
rm -f $new $old

Если в вашем $ PATH есть приведенный выше сценарий, вы можете:

overwrite manipulate sed 's/cat/dog/' manipulate

Чтобы упростить себе жизнь, вы можете использовать сценарий replace из той же книги:

# replace: replace  str1 in files with str2 in place
PATH=/bin:/usr/bin

case $# in
    0|2) echo 'Usage: replace str1 str2 files' 1>&2; exit 1
esac

left="$1"; right="$2"; shift; shift

for i
do
    overwrite $i sed "s@$left@$right@g" $i
done

Если заменить в вашем $ PATH , это также позволит вам сказать:

replace cat dog manipulate
3
ответ дан 30 November 2019 в 06:09
поделиться

Обходной путь с использованием дескрипторов открытых файлов:

exec 3<manipulate 

Предотвратить усечение открытого файла:

rm manipulate
sed 's/cat/dog/' <&3 > manipulate
-2
ответ дан 30 November 2019 в 06:09
поделиться

Возможно, -i - это gnu sed или просто старая версия sed, но в любом случае. Вы на правильном пути. Первый вариант, вероятно, самый распространенный, третий вариант - если вы хотите, чтобы он работал везде (включая машины Solaris) ... :) Это «стандартные» способы сделать это.

1
ответ дан 30 November 2019 в 06:09
поделиться

-i параметр недоступен в стандартном sed .

Ваши альтернативы - это ваш третий путь или perl .

0
ответ дан 30 November 2019 в 06:09
поделиться
Другие вопросы по тегам:

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