Замените символы с помощью группировки регулярных выражений на sed - PullRequest
3 голосов
/ 15 марта 2011

У меня есть текстовый файл, подобный следующему:

FOO BAR PIPPO PLUTO 31337 1010
FOOZ BAZ 130
VERY LONG LINE LIKE THIS THEN A NUMBER LIKE 42

Мне нужно превратить его в:

FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A-NUMBER-LIKE 42

Лучшее, что я мог сделать:

sed -re 's/([A-Z]+)( )([A-Z]+)/\1-\3/g'

но вывод

FOO-BAR PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG LINE-LIKE THIS-THEN A-NUMBER LIKE 42

Закрыть, но без сигары.Есть идеи о том, почему мое регулярное выражение не работает?

Ответы [ 3 ]

4 голосов
/ 15 марта 2011

Вы не можете иметь совпадающие совпадения.«BAR PIPPO» не обнаружен, потому что «BAR» уже использовался при сопоставлении «FOO BAR».

FOO BAR PIPPO PLUTO 31337 1010
------- ===========
   1         2

Попробуйте вместо этого:

$ sed -re 's/ ([A-Z])/-\1/g'

Обратите внимание, что это неесть совпадающие совпадения:

FOO BAR PIPPO PLUTO 31337 1010
   --  ==    --
   1   2     3
1 голос
/ 15 марта 2011
sed 's/ \([^0-9]\)/-\1/g'

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

Подтверждение концепции

$ cat ./infile
FOO BAR PIPPO PLUTO 31337 1010
FOOZ BAZ 130
VERY LONG LINE LIKE THIS THEN A NUMBER LIKE 42
THIS LINE HAS $ODD$ #CHARS# IN %IT% 42

$ sed 's/ \([^0-9]\)/-\1/g' ./infile
FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A-NUMBER-LIKE 42
THIS-LINE-HAS-$ODD$-#CHARS#-IN-%IT% 42
0 голосов
/ 15 марта 2011

Очень близко. Вам не нужно совпадать более чем с одной буквой - вам просто нужна буква пробела:

sed -Ee 's/([A-Z])( )([A-Z])/\1-\3/g' foo.txt 
FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A NUMBER-LIKE 42

(параметры sed скорректированы с учетом значения BSD)

...