Как разбить несколько пробелов на один с помощью sed?

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

 # iostat System configuration: lcpu=4 drives=8 paths=2 vdisks=0 tty: tin tout avg-cpu: % user % sys % idle % iowait 0.2 31.8 9.7 4.9 82.9 2.5 Disks: % tm_act Kbps tps Kb_read Kb_wrtn hdisk9 0.2 54.2 1.1 1073456960 436765896 hdisk7 0.2 54.1 1.1 1070600212 435678280 hdisk8 0.0 0.0 0.0 0 0 hdisk6 0.0 0.0 0.0 0 0 hdisk1 0.1 6.3 0.5 63344916 112429672 hdisk0 0.1 5.0 0.2 40967838 98574444 cd0 0.0 0.0 0.0 0 0 hdiskpower1 0.2 108.3 2.3 2144057172 872444176 # iostat | grep hdisk1 hdisk1 0.1 6.3 0.5 63345700 112431123 #iostat|grep "hdisk1"|sed -e"s/[ ]*/ /g" hdisk 1 0 . 1 6 . 3 0 . 5 6 3 3 4 5 8 8 0 1 1 2 4 3 2 3 5 4 

sed должен искать и заменять (и) несколько пробелов (/ [] * /) одним пространством (/) для всей группы (/ g) … но это не только делает это … его расстояние между каждым символом.

Что я делаю не так? Я знаю, что это должно быть что-то простое … AIX 5300-06

У меня есть другой компьютер с 10 жесткими дисками. Я использую это как параметр для другой программы для целей мониторинга.

Проблема, с которой я столкнулся, заключалась в том, что «awk» {print $ 5} 'не работает, потому что я использую $ 1 и т. Д. На вторичной стадии и дал ошибки команде Print. Я искал версию grep / sed / cut Что, кажется, работает:

 iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5 

[] Были «0 или более», когда я думал, что они означают «только один». Снятие скобок заставило его работать. Три очень хорошие ответы действительно быстро затрудняют выбор «ответа».

6 Solutions collect form web for “Как разбить несколько пробелов на один с помощью sed?”

Использование grep избыточно, sed может сделать то же самое. Проблема заключается в использовании * которое соответствует также 0 пробелам, вы должны использовать \+ вместо:

 iostat | sed -n '/hdisk1/s/ \+/ /gp' 

Если ваш sed не поддерживает \+ metachar, тогда сделайте

 iostat | sed -n '/hdisk1/s/ */ /gp' 

/[ ]*/ соответствует нулю или больше пробелов, поэтому пустая строка между символами совпадает.

Если вы пытаетесь сопоставить «одно или несколько пробелов», используйте один из следующих:

 ... | sed 's/ */ /g' ... | sed 's/ \{1,\}/ /g' ... | tr -s ' ' 

Измените оператора * на + . Вы сопоставляете ноль или более предыдущего символа, который соответствует каждому символу, потому что все, что не является пространством, это … um … нулевые экземпляры пространства. Вы должны соответствовать ОДИН или больше. На самом деле было бы лучше совместить два или более

Класс символов в квадратных скобках также не нужен для сопоставления одного символа. Вы можете просто использовать:

 s/ \+/ /g 

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

Обратите внимание, что вы также можете делать то, что вы пытаетесь сделать,

 iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5 

от

 iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done 

что может быть особенно полезно, если вы позже попытаетесь получить доступ к другим полям и / или вычислить что-то вроде этого:

 iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done 

Вы всегда можете совместить последнее вхождение в последовательности чего-либо типа:

 s/\(sequence\)*/\1/ 

И поэтому вы на правильном пути, но вместо того, чтобы заменять последовательность пространством, замените его своим последним вложением – одним пробелом. Таким образом, если последовательность пробелов согласована, последовательность сводится к одному пространству, но если нулевая строка сопоставляется, то нулевая строка заменяется на себя – и никакого вреда не бывает. Так, например:

 sed 's/\( \)*/\1/g' <<\IN # iostat System configuration: lcpu=4 drives=8 paths=2 vdisks=0 tty: tin tout avg-cpu: % user % sys % idle % iowait 0.2 31.8 9.7 4.9 82.9 2.5 Disks: % tm_act Kbps tps Kb_read Kb_wrtn hdisk9 0.2 54.2 1.1 1073456960 436765896 hdisk7 0.2 54.1 1.1 1070600212 435678280 hdisk8 0.0 0.0 0.0 0 0 hdisk6 0.0 0.0 0.0 0 0 hdisk1 0.1 6.3 0.5 63344916 112429672 hdisk0 0.1 5.0 0.2 40967838 98574444 cd0 0.0 0.0 0.0 0 0 hdiskpower1 0.2 108.3 2.3 2144057172 872444176 # iostat | grep hdisk1 hdisk1 0.1 6.3 0.5 63345700 112431123 IN 

ВЫВОД

 # iostat System configuration: lcpu=4 drives=8 paths=2 vdisks=0 tty: tin tout avg-cpu: % user % sys % idle % iowait 0.2 31.8 9.7 4.9 82.9 2.5 Disks: % tm_act Kbps tps Kb_read Kb_wrtn hdisk9 0.2 54.2 1.1 1073456960 436765896 hdisk7 0.2 54.1 1.1 1070600212 435678280 hdisk8 0.0 0.0 0.0 0 0 hdisk6 0.0 0.0 0.0 0 0 hdisk1 0.1 6.3 0.5 63344916 112429672 hdisk0 0.1 5.0 0.2 40967838 98574444 cd0 0.0 0.0 0.0 0 0 hdiskpower1 0.2 108.3 2.3 2144057172 872444176 # iostat | grep hdisk1 hdisk1 0.1 6.3 0.5 63345700 112431123 

Все сказанное, вероятно, гораздо лучше избегать регулярных выражений в этой ситуации и вместо этого:

 tr -s \ <infile 

Вы можете использовать следующий скрипт для преобразования нескольких пространств в одно пространство, TAB или любую другую строку:

 $ ls | compress_spaces.sh # converts multiple spaces to one $ ls | compress_spaces.sh TAB # converts multiple spaces to a single tab character $ ls | compress_spaces.sh TEST # converts multiple spaces to the phrase TEST $ compress_spaces.sh help # show the help for this command 

compress_spaces.sh

 function show_help() { IT=$(CAT <<EOF usage: {REPLACE_WITH} NOTE: If you pass in TAB, then multiple spaces are replaced with a TAB character no args -> multiple spaces replaced with a single space TAB -> multiple spaces replaced with a single tab character TEST -> multiple spaces replaced with the phrase "TEST" ) echo "$IT" exit } if [ "$1" == "help" ] then show_help fi # Show help if we're not getting data from stdin if [ -t 0 ]; then show_help fi REPLACE_WITH=${1:-' '} if [ "$REPLACE_WITH" == "tab" ] then REPLACE_WITH=$'\t' fi if [ "$REPLACE_WITH" == "TAB" ] then REPLACE_WITH=$'\t' fi sed "s/ \{1,\}/$REPLACE_WITH/gp" 
  • печатать только строки, у которых есть последняя непустая ячейка, которая начинается со слова «Failed» в CSV-файле в Linux
  • Как извлечь данные из файла и построить имя файла из одного из значений
  • Удалить строку, соответствующую шаблону, если следующая строка не соответствует другому шаблону
  • Как извлечь одно значение из однострочных кортежей?
  • Изменить значение в таблице
  • Поведение POSIX привязок sed и $ regex с многострочными пространствами шаблонов
  • Поиск файла для числа, которое находится между двумя конкретными номерами
  • Как удалить повторяющиеся буквы с помощью sed?
  • Escape> ');} </ in sed
  • \ n печатает n вместо новой строки при использовании sed в MaxOSX
  • Обрезать линии между двумя разделителями
  • Выполнение функции Prime Key с использованием Sed в Bash
  • Linux и Unix - лучшая ОС в мире.