#awk #sed
#awk #sed
Вопрос:
Я использую следующую команду sed для замены строки
sed -i "s|find string|replace string|g" inputfile
Но это заменит все вхождения. (Я думаю, g
это для Global
замены)
Как я могу выполнить замену строки только указанное количество раз, т. е. 10 или 15 раз, используя sed, grep или awk ..?
Комментарии:
Ответ №1:
Вы могли бы сделать:
perl -pe '$i while($i < 10 amp;amp; s/pattern/replace/)' input
В awk:
awk '{ while( i< c amp;amp; sub( "pattern", "replace" )) i =1}1' c=10 input
Комментарии:
1.
-p
заставляет perl перебирать свои входные данные и печатать каждую строку, и-e
просто указывает код для запуска (следующий аргумент после-e
).2.
i =1
это то же самое, чтоi
3. @jotne
i
— это выражение, ноi =1
это оператор. В качестве побочного эффекта,i
увеличиваетсяi
, так что в этом смысле они семантически похожи, но они оцениваются по-разному при использовании в RHS присваивания. Я нахожу это гораздо более удобным в использованииi =1
, поскольку это проясняет намерение.
Ответ №2:
pur sed но лучше не использовать sed для решения такой проблемы, предпочитайте awk (или perl)
sed -n -e '1h;1!H
$ {s/.*//;x
t loop
:loop
s|find string|replace string|
t occur
b print
:occur
x
s/$/o/
t count
:count
s/o{10}/amp;/
x
t print
b loop
:print
p
}' YourFile
10 в s/o{10}/amp;/
— это желаемое количество встреч. использование s//;t label
как если бы /goto. без ‘else’, много s//;t
.
Сначала весь файл необходимо загрузить в рабочий буфер (по умолчанию sed работает на строку). Кроме того, в качестве счетчика используется вторичный буфер.
Комментарии:
1. Хорошая техника. Но нет необходимости считывать весь файл во временный буфер:
sed ':loop; x; s/o{10}/amp;/; x; t; s/pattern/replace/; t count; b; :count; x; s/^/o/; x; t loop;'
Ответ №3:
Вот другая awk
версия.
awk 'c amp;amp; sub("pattern","replace") {c--}1' c=2 file
Ответ №4:
Вот более читаемая awk
версия:
awk '{for(i=0; i<15; i ) sub("pattern", "replacement"); print $0}' file