
Я хотел захватить \n в переменной (предположим a) и подставить $a перед шаблоном поиска в файле (abc.txt)
может ли кто-нибудь подсказать мне решение?
> cat abc.txt
hi how are you how is your health
> echo $a
\
ожидаемый результат (шаблон поиска - how
)
hi \
how are you \
how is your health
решение1
В оболочке типа Bourne или rc
a='
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
передаст a
переменную окружения , perl
содержащую символ новой строки, и perl
вставит содержимое этой переменной перед каждым вхождением pattern
в содержимом abc.txt
.
Чтобы присвоить любой символ, x
отличный '
от переменной в оболочках типа Bourne, можно использовать:
a='x'
Итак, для обратного слеша:
a='\'
Для новой строки:
a='
'
Для управляющих символов, таких как новая строка, но это было бы еще хуже, например, для забоя или возврата каретки, поскольку это делает код менее разборчивым.
ksh93 ввел новую $'...'
форму кавычек для указания этих символов в экранированной форме. Другие оболочки, такие как bash
, zsh
, mksh
или FreeBSD sh
скопировали и расширили (как $'\uXXXX'
форма, добавленная zsh
) ее с тех пор.
В этих оболочках вы можете использовать:
a=$'\n' a=$'\b' a=$'\r' a=$'\\' a=$'\''
Для назначения символа новой строки, возврата на одну позицию, возврата каретки, обратной косой черты или одинарной кавычки.
Этот оператор цитирования пока не является стандартным, поэтому вы не можете использовать его в переносимом sh
скрипте. Стандартной альтернативой является использование:
a=$(printf '\b')
для backspace например, но это не работает для новой строки, так как подстановка команд ( $(cmd)
) удаляет конечные символы новой строки из вывода cmd
. Приходится прибегать к таким хакам, как:
nl=$(printf '\n.'); nl=${nl%.}
(то есть добавить .
и удалить его потом), чтобы сохранить его.
Обратите внимание, что он perl
также понимает эти \n
обозначения в своем коде, поэтому вы можете сделать следующее:
perl -pe 's/pattern/\n$&/g' < abc.txt
Реализация GNU sed
(и несколько других в настоящее время) также поддерживают это:
sed 's/pattern/\n&/g' < abc.txt
но это не стандарт. Стандартно, новая строка в заменяющей части команды s
должна sed
быть выражена обратной косой чертой, за которой следует фактически новая строка, так что это будет:
backslash='\' newline='
'
sed "s/pattern/$backslash$newline&/g" < abc.txt
Или без переменных:
sed 's/pattern/\
&/g' < abc.txt
Итак, если вы хотите вставить и обратную косую черту, и новую строку перед pattern
, вам нужно:
sed 's/pattern/\\\
&/g' < abc.txt
Всего 3 обратных слеша, два для буквального обратного слеша и один для новой строки. Или с помощью perl
:
perl -pe 's/pattern/\\\n$&/g' < abc.txt
Или с вашей a
переменной:
a='\
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
решение2
Вы также можете использовать собственные команды bash, используя:
cat abc.txt | sed -e 's/how/\nhow/g' | while read line; do echo "$line \\"; done