Является ли sed auto заменой на месте? - PullRequest
0 голосов
/ 27 мая 2019

У меня есть этот код, который я хочу заменить конкретным шаблоном, но не замену нескольких на месте.

 echo "ss qq" | sed  "s/ss/qq/g; s/qq/dd/g;"

Результат -

dd dd

и желаюэто будет

qq dd

Также с помощью "зацикливания" мы получим тот же результат.

echo "ss qq" | sed  ":loop; s/ss/qq/g; s/qq/dd/g; t loop;"

мелкая, очень разочаровывающая ошибка !!

Любое предположение, почему этопроисходит?

Ответы [ 4 ]

2 голосов
/ 27 мая 2019

Что касается «почему это происходит»: sed принимает входные данные построчно, затем последовательно применяет каждую команду.Это станет более понятным, если вы посмотрите на выходные данные отладки GNU sed (4.6 или новее) для вашей команды:

$ sed --debug 's/ss/qq/g;s/qq/dd/g' <<< 'ss qq'
SED PROGRAM:
  s/ss/qq/g
  s/qq/dd/g
INPUT:   'STDIN' line 1
PATTERN: ss qq           # Pattern space before first command is applied
COMMAND: s/ss/qq/g
MATCHED REGEX REGISTERS
  regex[0] = 0-2 'ss'
PATTERN: qq qq           # Pattern space before second command is applied
COMMAND: s/qq/dd/g
MATCHED REGEX REGISTERS
  regex[0] = 0-2 'qq'
PATTERN: dd dd
END-OF-CYCLE:
dd dd
0 голосов
/ 28 мая 2019

Это может сработать для вас (GNU sed):

sed  's/ss\|qq/\n&/;:a;s/\nss/qq\n/;s/\nqq/dd\n/;s/\n\(.\)/\1\n/;ta;s/\n//' file

Это вводит маркер в виде новой строки о том, где произошла последняя замена.В конце строки маркер удаляется.

Причина этого маркера заключается в том, что каждый вызов команды подстановки начинается заново с начала строки, а не с того места, где закончилась последняя подстановка.Флаг g может запутать проблему, но относится только к текущему вызову подстановки.

Как уже упоминалось, лучший способ состоит в том, чтобы использовать альтернативу для первой замены и заменить ее глобально как последнююкоманда.

sed 's/ss/\n/g;s/qq/dd/g;s/\n/qq/g' file 
0 голосов
/ 27 мая 2019

Возможно, это поведение команды y///, которую вы ищете:

▶ echo "ss qq" | sed 'y/sq/qd/'                 
qq dd

Это преобразует все s в q и все q в d символхарактер.

0 голосов
/ 27 мая 2019

что бы это было

qq dd

затем вы делаете замену в обратном порядке:

изменить sed "s/ss/qq/g;s/qq/dd/g;" -> sed "s/qq/dd/g;s/ss/qq/g;"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...