Как я могу заменить несколько экземпляров символа одинаковым количеством экземпляров другого символа в linux sed?

Мне нужно заменить повторяющийся набор символов (2 или более) на точное количество заменяющих символов. Мне нужно сделать это либо с помощью sed, либо внутри vi.

Примеры

"abc,,,def" becomes "abc|||dev"
"1245d,,,,,22" becomes "1245d|||||22"

Спасибо

3 ответа

Извините, что не комментирую, у меня нет 50 репутации.

Это решение не удастся, если есть больше шаблонов, таких как abc,,,def,g,

sed -n 's/[^,],,/&/;tsubs;p;d;:subs s/,/|/g;p' <<<'abc,,,def
abc,,def
abc,,,def,g
abc,def'

Труба через sed, лайк

echo "abc,,,def" | sed 's/,/|/g'

но я бы порекомендовал использовать

tr ',' '|'

в этом случае.

Это практически невозможно из-за работы регулярных выражений. Как уже указывал jvb, решение является простым (хотя и не обязательно коротким), если известно максимальное количество последовательных исходных символов. Если нет, то можно сначала изменить все исходные символы, а затем снова изменить отдельные символы на втором шаге. Однако это работает только в том случае, если целевой символ не встречается во входном потоке или если вы можете использовать символ, о котором известно, что он не встречается во входном потоке, в качестве промежуточной цели.

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

tr ',' '|' < file | sed 's/\([^|]\)|\([^|]\)/\1,\2/;s/^|\([^|]\)/,\1/;s/\([^|]\)|$/\1,/'

или же

sed 's/,/|/g;s/\([^|]\)|\([^|]\)/\1,\2/;s/^|\([^|]\)/,\1/;s/\([^|]\)|$/\1,/' file

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

Другие вопросы по тегам