как заменить каждый ,, с,?, используя sed? - PullRequest
0 голосов
/ 27 сентября 2019

Я пробовал следующую команду:

echo "123456,,7,,,,890" | sed 's/,,/\,?,/g'

Результат:

123456,?,7,?,,?,890

Но результат, который я хочу получить:

123456,?,7,?,?,?,890

Может ли кто-нибудь мне помочь?Спасибо ~!

Ответы [ 2 ]

3 голосов
/ 27 сентября 2019

Ваша проблема в том, что ,, в результате никогда не был замечен опцией g.
Одно из двух исходит от замены.
С вашим специальным желаемым выводом (я бы ожидалтолько три вместо четырех замен ...) вам нужно посмотреть на результат одной замены и заменить снова, пока замена больше не произойдет.
Этого можно добиться, создав цикл с :a, то естьпометьте «a», а затем вернитесь после успешной замены на ta, «на метку a».
(g становится ненужным, но может быть более эффективным. Пора найти его в вашей среде.)

sed ':a;s/,,/\,?,/g;ta'

результат

"123456,?,7,?,?,?,890"
2 голосов
/ 27 сентября 2019

Регулярные выражения не могут совпадать с перекрывающимися интервалами.Таким образом, если у вас есть ,,,,, первые две запятые будут первым совпадением, а третья и четвертая запятые будут составлять второе совпадение.Нет никакого способа сопоставить вторую и третью запятую с /??/.

Как правило, это можно сделать, используя предпросмотр, чтобы одна из запятых не была частью совпадения;но sed не поддерживает это.Таким образом, вы можете переключиться на более мощный движок регулярных выражений, такой как perl:

echo "123456,,7,,,,890" | perl -pe 's/,(?=,)/,?/g'

В качестве альтернативы, поскольку в вашем конкретном случае вы пропустите любую другую соседнюю пару запятых, вы можете просто запустить sed дважды:

echo "123456,,7,,,,890" | sed 's/,,/,?,/g' | sed 's/,,/,?,/g'

или объединить две операции в один sed вызов:

echo "123456,,7,,,,890" | sed 's/,,/\,?,/g; s/,,/,?,/g'
...