почему экранирующие символы и регулярные выражения не работают с командой sed? - PullRequest
0 голосов
/ 05 апреля 2019

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

[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/\s+/\n/g"
abc  def    gks       dps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/\s\{1,\}/\n/g"
abc  def    gkn       dpn
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/\n/g"
abcndefngksndps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/:/g"
abc:def:gks:dps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ +/:/g"
abc  def    gks       dps

Но на самом деле работает только один.

[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/:/g"
    abc:def:gks:dps

Кажется, что набор символов \s и специальный символ + в регулярном выражении не работают с командой sed.И \n не распознается как новая строка.Может ли кто-нибудь сказать мне, почему или дать некоторую подсказку.Спасибо.

Ответы [ 2 ]

3 голосов
/ 05 апреля 2019

sed соответствует базовым регулярным выражениям, а метасимвол + - из расширенных регулярных выражений.Сокращение \s для класса символов POSIX [[:space:]] будет работать только в некоторых seds (например, в GNU sed) как расширение.Точно так же \n будет работать только как «новая строка» в некоторых seds, в то время как в любом sed вы можете использовать обратную косую черту, за которой следует буквальный символ новой строки.Использование двойного (") вместо одинарных кавычек (') в сценарии приводит к тому, что он становится доступным для оболочки, и, следовательно, требует дополнительной экранирования от обратной косой черты - всегда используйте одинарные кавычки вокруг строк или сценариев, если только у вас нет особой необходимостидвойные кавычки (например, чтобы позволить переменной расширяться) и используйте только двойные, если у вас нет особой необходимости ни в одном (например, чтобы разрешить расширение подстановочного знака).

Чтобы сделать то, что вы хотите в любом sed POSIX, это:

$ echo 'abc  def    gks       dps' | sed 's/[[:space:]][[:space:]]*/\
/g'
abc
def
gks
dps

, но это будет работать с GNU sed (обратите внимание на -E для включения ERE для + - это поддерживается в GNU sed и OSX / BSD sed, но из этих 2 seds будет поддерживать только GNU sed\s и \n):

$ echo 'abc  def    gks       dps' | sed -E 's/\s+/\n/g'
abc
def
gks
dps
2 голосов
/ 05 апреля 2019

Есть несколько проблем. Прежде всего, sed использует базовые регулярные выражения по умолчанию, которые не распознают +. Используйте модификатор -E для расширенных регулярных выражений, которые делают.

Во-вторых, sed не распознает \n; но вы можете использовать ANSI C, цитируя , чтобы bash понял это. Однако, если вы просто используете \n, у вас будет просто разрыв строки в вашем шаблоне sed, так что вам нужно избежать прерывания строки, чтобы sed использовал его буквально; так что вам нужно \\ для побега и \n для разрыва строки, всего три обратных слеша.

Наконец, \s как символьный класс также не распознается vanilla sed (но он доступен в GNU sed, который используется в дистрибутивах Linux). Вместо этого используйте буквенное пространство, если вам нужна совместимость, например, с OSX (или brew install gnu-sed).

echo "abc  def    gks       dps" | sed -E $'s/ +/\\\n/g'
# => abc
#    def
#    gks
#    dps
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...