![Как добавить текст после n-го вхождения в bash?](https://rvso.com/image/169443/%D0%9A%D0%B0%D0%BA%20%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%D1%82%D0%B5%D0%BA%D1%81%D1%82%20%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%20n-%D0%B3%D0%BE%20%D0%B2%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%B2%20bash%3F.png)
Допустим, у меня есть helloworld.txt:
hello world
Используя sed:
sed 's/w*/goodbye/' helloworld.txt
Дает мне:
goodbyehello world
И:
sed 's/$/goodbye/' helloworld.txt
Дает мне:
hello worldgoodbye
Но как мне добавить текст?послепервое появление, поэтому выглядит это так:
hellogoodbye world
решение1
Предположим, что вы говорите о вставке текста до или после определенных вхожденийсловав строке текста.
$ echo 'word1 word2 word3 word4' | sed 's/\<[[:alnum:]]\{1,\}\>/newword &/'
newword word1 word2 word3 word4
$ echo 'word1 word2 word3 word4' | sed 's/\<[[:alnum:]]\{1,\}\>/& newword/'
word1 newword word2 word3 word4
$ echo 'word1 word2 word3 word4' | sed 's/\<[[:alnum:]]\{1,\}\>/& newword/2'
word1 word2 newword word3 word4
$ echo 'word1 word2 word3 word4' | sed 's/\<[[:alnum:]]\{1,\}\>/& newword/3'
word1 word2 word3 newword word4
$ echo 'word1 word2 word3 word4' | sed 's/\<[[:alnum:]]\{1,\}\>/& newword/4'
word1 word2 word3 word4 newword
Это вставляет строку newword
(и предшествующий ей пробел) в разные места заданной строки.
Выражениеsed
s/\<[[:alnum:]]\{1,\}\>/& newword/2
заменит второе совпадение непустой строки, состоящей только из буквенно-цифровых символов.
Флангирование \<
и \>
соответствует границе нулевой ширины между словом и не-словом в начале и конце совпадения соответственно (в GNU sed
вы также можете использовать \b
для этого). Это гарантирует, что вы сопоставляете целые слова, но на самом деле не нужно с заданными данными (я использую шаблоны границ слов, потому что это подчеркивает намерение того, что я делаю).
— это \{1,\}
модификатор, который записывается +
в расширенном регулярном выражении и заставляет предыдущий шаблон совпадать по крайней мере один раз (но sed
по умолчанию использует базовые регулярные выражения).
В заменяемой части &
будет бит входной строки, который фактически соответствует шаблону, а 2
в конце — флаг, который заставляет замену выполняться только для второго неперекрывающегося совпадения.
Примерыв вашем комментарии(что почти то же самое, но без пробела):
$ echo '7DF258 01DB-MET-RX PASS' | sed 's/\<[[:alnum:]-]\{1,\}\>/&FIDUCIAL/'
7DF258FIDUCIAL 01DB-MET-RX PASS
$ echo '7DF258 01DB-MET-RX PASS' | sed 's/\<[[:alnum:]-]\{1,\}\>/&FIDUCIAL/2'
7DF258 01DB-MET-RXFIDUCIAL PASS
Обратите внимание, что в примере, который вы привели в комментариях, «слова» также содержат тире, поэтому я использую , [[:alnum:]-]
а не просто [[:alnum:]]
.