Основная проблема, в данном случае, заключается в том, что регулярное выражение не допускает перекрытия при разборе его с sed 's/ere/str/g'
или awk '{gsub(ere,str,$0)}'
. Этот комментарий хорошо объясняет, как вы можете обойти это в sed
с помощью команды t<label>
, что означает: если произошло изменение в пространстве шаблона, перейдите к Комментарий показывает общий способ сделать это. Альтернативой этому правилу awk будет:
$ awk '{while(match($0,ere)) gsub(ere,str)}'
Альтернативное решение sed
в случае примера OP может использовать следующую идею:
- дублировать все запятые. Так как мы ищем строки вида ", t", это дублирование позволяет избежать дублирования, используя
s
. - , поскольку перекрытие невозможно, замените все ", f," на ", 0," иall ", t," with ", 1,".
- Теперь мы можем снова вернуть все дублированные запятые. Поскольку перекрытие не допускается, последовательности, подобные
,,,,
, будут преобразованы в ,,
, а не ,
В POSIX sed это выглядит следующим образом:
$ sed -e 's/,/,,/g' -e 's/,f,/,0,/g' \
-e 's/,t,/,1,/g' -e 's/,,/,/g' file > file.tmp
$ mv file.tmp file
СGNU SED мы можем сделать это за один раз:
$ sed -i 's/,/,,/g;s/,f,/,0,/g;s/,t,/,1,/g;s/,,/,/g' file
С awk это будет выглядеть так:
$ awk 'BEGIN{FS=",";OFS=FS FS}
{$1=$1;gsub(/,f,/,",0,");gsub(/,t,/,",1,");gsub(OFS,FS)}1' file > file.tmp
$ mv file.tmp file