sed заменяет все символы табуляции и пробелы одним пробелом

23

Я получил строку вроде следующего:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

теперь я хочу заменить все табуляции / пробелы между записями только одним пробелом, чтобы я мог легко использовать его с cut -d " "

Я попробовал следующее:

sed "s/[\t[:space:]]+/[:space:]/g"

и различные варианты, но не могли заставить его работать. Любые идеи?

Zulakis
источник
Попробуйте: sed -r -e "s / [\ t \] + / / g"
RJS
Ваш вариант cutподдержки -w?
Кондыбас

Ответы:

40

использование sed -e "s/[[:space:]]\+/ /g"

Вот объяснение:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

Для замены вам нужно только вставить пробел. [:space:]не будет работать там, так как это аббревиатура для класса персонажа, а движок регулярных выражений не будет знать, какой символ поместить туда.

+Должны быть экранированы в регулярном выражении , потому что с СЕПГ регулярных выражений +является нормальным характер , тогда как \+это метасимволом для «один или более». На странице 86 « Освоение регулярных выражений» Джеффри Фридл упоминает в сноске, что ed и grep использовали экранированные скобки, потому что «Кен Томпсон считал, что регулярные выражения будут использоваться в основном для работы с кодом C, где необходимость сопоставлять необработанные скобки будет более распространенной, чем обратная ссылка «. Я предполагаю, что он чувствовал то же самое по отношению к знаку плюс, отсюда и необходимость избегать его, чтобы использовать его в качестве метасимвола. Легко быть запутанным этим.

В СЭД вам нужно бежать +, ?, |, (, и ). или используйте -r для использования расширенного регулярного выражения (тогда это выглядит как sed -r -e "s/[[:space:]]\+/ /g"илиsed -re "s/[[:space:]]\+/ /g"

морская звезда
источник
Это тоже убирает вкладки? Можете ли вы объяснить, почему вы используете \+вместо просто +?
Зулакис
Хорошо, я понял. [[: space:]] равно [\ t \ r \ n \ v \ f]. Но не могли бы вы объяснить, почему вы используете\+
Zulakis
3
[[: space:]] эквивалентно '\ s', поэтому более короткая версия - "s / \ s \ + / / g"
3моло,
2
Базовые регулярные выражения используют обратную косую черту перед знаком плюс, когда они означают «один или несколько из предыдущего символа или группы», источник developer.apple.com/library/mac/#documentation/opensource/… .
3моло
Ааа, я понимаю! Я не знал, что были разные версии регулярных выражений. Спасибо
Zulakis
6

Вы можете использовать -s("squeeze") параметр tr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

Класс [:blank:]персонажа состоит из пробелов и табуляции.

Бенджамин В.
источник
-2

Мне нравится использовать следующий псевдоним для Bash. Основываясь на том, что написали другие, используйте sed для поиска и замены нескольких пробелов одним пробелом. Это помогает получить последовательные результаты от резки. В конце я запускаю его через sed еще раз, чтобы изменить пространство на табуляцию, чтобы его было легче читать.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
Безопасность ЦНС miked
источник
Как это отвечает на вопрос?
Тонин