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

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

$ 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

  • Замените регулярное выражение на строку, содержащую совпадение
  • Лучший способ вставить блоки HTML в bash
  • Как мне скопировать папку, а не только содержимое папки?
  • Какой самый простой способ определить, какие сигналы отправляются процессу?
  • Как удалить строку, если строка является единственной вещью на линии
  • Как получить JSON STRING из данной строки
  • Мой вопрос касается конкретно этого регулярного выражения, а не другого подхода к тому, чтобы делать то же самое. я

  • Замена символа подчеркивания запятой и удаление двойных кавычек в CSV
  • regex - найти недопустимый символ
  • Греблирование фигур строки для создания новой строки
  • Если Mac OS X является UNIX, почему она не открыта и лицензия является собственностью?
  • Подключиться к Webdav (https) с помощью домена \ пользователя
  • Как использовать sed для замены ключей в файле с помощью регулярного выражения?
  • 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 - лучшая ОС в мире.