Почему эта замена регулярных выражений не работает?

У меня есть файл в следующем формате:

$ cat myfile 12 42956 Cinema - 3D/Multiplex 7 12560 Status Update 5 184 Movie 

Я пытаюсь добавить двойные кавычки к текстовому описанию.
Я не могу понять, почему следующее регулярное выражение не работает:
$ sed -E 's/\b[0-9]+\b\s*\b[0-9]+\b\s*([^\s]+)/"\1"/g' myfile

Мой вопрос касается конкретно этого регулярного выражения, а не другого подхода к тому, чтобы делать то же самое. я

  • Разница в поведении команды Sed Command
  • Объединение двух CSV по сравнению только с определенным столбцом
  • Как заменить символ || с | "" | использование sed
  • Строка печати содержит максимальное и минимальное значение
  • Группировка строк в гетерогенные подмножества
  • Вырезать строку-Catch: есть файл с тем же именем, что и строка в том же пути
  • удалять дубликаты на основе значения другого столбца
  • Вставить текст в определенные строки файла?
  • 3 Solutions collect form web for “Почему эта замена регулярных выражений не работает?”

    Насколько я знаю, \s является регулярным выражением Perl, которое совпадает с [[:blank:]] в sed . Внутри [ ... ] , \s означает «an \ и s ». Также обратите внимание, что даже если [^\s]+ было бы таким же, как [^␣]+ , это не соответствовало бы Status Update из-за пространства в середине.

    Замена заменит все совпадения первой группой в двойных кавычках. Вероятно, вы хотите поймать все три столбца, иначе вы получите только последний столбец. И поскольку вы пытаетесь сопоставить всю строку, вы должны привязать выражение в начале и конце с помощью ^ и $ и сбросить флаг g в конце.

    Альтернатива:

     $ sed -E 's/[[:alpha:]].+/"&"/' myfile 12 42956 "Cinema - 3D/Multiplex " 7 12560 "Status Update " 5 184 "Movie " 

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

    Данные в вопросе имели пробелы в конце, и эти цитаты будут включать эти. Чтобы избежать пробелов в конце:

     $ sed -E -e 's/[[:blank:]]*$//' -e 's/[[:alpha:]].+/"&"/' myfile 12 42956 "Cinema - 3D/Multiplex" 7 12560 "Status Update" 5 184 "Movie" 

    С другой стороны,

     while read -rabc; do printf '%d\t%d\t"%s"\n' "$a" "$b" "$c"; done <myfile 12 42956 "Cinema - 3D/Multiplex" 7 12560 "Status Update" 5 184 "Movie" 
     sed -E 's/\b([0-9]+\b\s*\b[0-9]+)\b\s*([^\s]+)/\1 "\2"/g' myfile 

    Это добавляет двойные кавычки вокруг вашего текста.

    Сохраняя цифры и пробелы в группе \1 и строку в другой группе (\ 2), sed выводит группу 1 (\ 1), а затем пробел, за которым следует двойная кавычка, за которой следует вторая группа (\ 2), за которой следует окончательная двойная кавычка.

    Вы можете сократить это немного, объединив все цифры и пробелы в одной группе ([0-9, ]*) и все, что после цифр в другой группе (.+) .

    Это дает:

     sed -E 's/([0-9, ]*)(.+)/\1 "\2"/g' myfile 12 42956 "Cinema - 3D/Multiplex" 7 12560 "Status Update" 5 184 "Movie" 

    Поскольку Mac OSX sed не поддерживает \s . Только GNU sed поддерживает \s .

    В Mac OSX \s не работает, даже при цитировании $'' ANSI-C.

     $ echo $'1\t2 3' | sed 's/\s//g' 1 2 3 $ echo $'1\t2 3' | sed $'s/\s//g' 1 2 3 

    Вместо этого вы можете использовать [[:space:]]

     $ echo $'1\t2 3' | sed 's/[[:space:]]//g' 123 

    Или вы можете использовать [ \t] , но вам понадобится котировка $'' ANSI-C для символа табуляции.

     $ echo $'1\t2 3' | sed $'s/[ \t]//g' 123 
    Linux и Unix - лучшая ОС в мире.