Как использовать sed для записи в имя файла, сохраненное в переменной?

Как использовать sed для записи в имя файла, сохраненное в переменной?

bashКак из скрипта sedзаписать в файл, имя которого хранится в переменной bash? Перенаправление вывода не подойдет, поскольку я хочу редактировать один файл на месте, перетаскивая строки, соответствующие регулярному выражению, в другой файл и удаляя их в первом файле.

Что-то вроде:

sed -i '/^my regex here$/{;w file2;d;}' file1

...но где file1и file2оба они на самом делепеременныечтодержатьимена файлов. (Например file2=$(mktemp), .)

Так что на самом деле мне нужно расширение переменной для имени файла, но не расширение для остальной части команды sed, и оставить все это как один аргумент, передаваемый команде sed.

По какой-то причине следующее не работает:

sed -i '/my regex here/{;w '"$file2"';d;}' $file1

Там написано «unmatched {», и я не понимаю, почему.

Как-нибудь я могу это сделать?

решение1

Поскольку вы используете одно sedвыражение, все, что следует после w(включая }),интерпретируется какwfileимя:

Аргумент wfileзавершает команду редактирования.

Это можно увидеть, если добавить вторую команду, }например:

sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1

то соответствующие строки my regex hereбудут сохранены в файле с именем whatever;d;}where whateveris what is то, что $file1расширяется в.
Правильный синтаксис — через отдельные команды, либо с несколькими выражениями:

sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2

или по одной команде в строке:

sed '/my regex here/{
w '"$file1"'
d
}
' $file2

решение2

Я нашел ответ наПереполнение стекав разделе «Как сообщить команде sed 'w', где заканчивается имя файла?»

Как отметил Тердон, проблема не в переменной, но она не имеет никакого отношения и к фигурным скобкам; попробуйте sed '/^l/w testing;p', и вы увидите, что никаких ошибок не возникает, а все строки, начинающиеся с , записываются lв файл с именем testing;p.

На самом деле проблема заключается в отсутствии символа новой строки после имени файла.

Поэтому ответом будет либо использование встроенного символа новой строки в команде sed:

sed -i '/my regex here/{;w '"$file2"'
d;}' $file1

Или, что гораздо чище, используйте два отдельных -eаргумента:

sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1

Если вам не нравятся две соседние кавычки (на которые вы можете легко наступить), просто поместите команду записи в отдельный аргумент:

sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1

решение3

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

Более подробную информацию о кавычках переменных в bash можно найти здесьсвязь

Связанный контент