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 whatever
is 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 можно найти здесьсвязь