Используя sed, как отформатировать одно слово на строку, удалив пробел

здесь документы, как упомянуто и Kevin и Gilles выше, или простая передача по каналу будут работать во многих случаях.

Для более сложных ситуаций можно хотеть изучить, Ожидают или подобный (например, Ожидание:: Простой модуль CPAN является очень простой в использовании реализацией жемчуга). лично, я предпочитаю модуль жемчуга (Ожидайте себя, tcl), но существуют реализации для многих общих языков сценариев. Даже возможно записать очень примитивную реализацию идеи в sh или использовании удара, в то время как и читают.

Общее представление об Ожидает, и подобные инструменты должен ожидать указанной строки или шаблона в выводе программы, и затем подать его, независимо от того, что введено, Вы хотите.

Использование типичного примера должно автоматизировать вход в систему путем "ожидания" (т.е. ожидания) строка "ogin": отправьте имя для входа в систему, затем ожидайте строку "слово": и отправьте пароль.

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

... и не забывайте отправлять свой патч к myprogram назад в восходящем направлении :) Даже если им не нравится способ, которым Вы кодировали его, им могло бы понравиться, когда идея достаточно добавила опцию самим. Восходящий поток devs имеет тенденцию ценить людей, которые выходят из их торцов и вносят, а не требуют или жалуются.

5
13.04.2017, 15:36
5 ответов

Можно использовать tr:

tr -s "[[:blank:]]" "\n" < file | grep .

[:blank:] класс символов включает весь горизонтальный пробел. -s сжимает или уменьшает несколько символьных случаев до одного.

grep удаляет пустую строку (если есть).

8
27.01.2020, 20:32
  • 1
    спасибо за предложение, но это не использует sed, и пустая строка в начале входного файла не удалена, и новая строка не добавляется после последнего слова.С уважением. –  Yann Droneaud 17.06.2013, 11:49

Попробуйте это

sed -e 's/[[:space:]]/\n/g' | grep -v '^$'

Это использует обоих grep и sed, но я надеюсь, что хорошо (если Вы имеете sed в системе Вы обычно имеете grep также)

4
27.01.2020, 20:32
  • 1
    @Karel-Bilek: в то время как это работает, например, это помещает слова один на строку, удаляя все пробелы, добавьте новую строку в EOF: это могло быть сделано с единственным вызовом 'sed' без какого-либо другого инструмента Unix?С уважением. –  Yann Droneaud 17.06.2013, 11:54
  • 2
    @ydroneaud: don_crissti записал точно это. Но этому нужна версия GNU sed. Не уверенный в стандарте UNIX. –  Karel Bílek 18.06.2013, 00:11
  • 3
    @KarelBílek не точно, поскольку это использует 2 вызова sed с каналом. Я хотел бы только один sed вызов. –  Yann Droneaud 18.06.2013, 16:31

Не sed, но:

gawk length RS='[[:space:]]+' file

Это рассматривает любую последовательность пробела как разделитель записей и печатает каждую непустую запись.

4
27.01.2020, 20:32
  • 1
    @don_crissti, ведущие пробелы на самом деле удалены, но awk рассматривает пустую строку перед пробелом как пустая запись. Я обновил, чтобы только распечатать непустые записи –  glenn jackman 14.06.2013, 21:45
  • 2
    Чтобы убедить меня использовать awk вместо sed, необходимо показать, как заменить несколько шаблонов в файле при форматировании его с POSIX awk.С уважением. –  Yann Droneaud 17.06.2013, 11:56

Поскольку OP, кажется, непреклонен в использовании «единого вызова» sed, вот один:

Подход без -разделения слов с частичным шаблоном -скрытие пробелов:

sed -n -e 's/^\W*//' -e 's/\(\W\+\)/\n/gp' words.txt

РЕДАКТИРОВАТЬ :Обратите внимание, что, как указал @don _crissti, это решение не является полным, так как оно не может распечатать слова, которые появляются в строке сами по себе, а также вставить новая строка в самом конце вывода, если в файле отсутствует завершающая новая строка. Чтобы исправить эту проблему, см. Следующее, крайне уродливое решение.

Основная проблема с sedзаключается в том, что пространство шаблонов, на котором работает каждое выражение -e, всегда определяется строками. Если вы вставите новые строки, тем самым изменив структуру строки между первым выражением и следующим, следующее выражение не сможет работать с обработанными данными.

Пояснение:

  • Во-первых, начальные пробелы, если они есть, обрабатываются в каждой строке. Те, что полностью из него состоят, превращаются в пустые строки, сохраняя при этом длину строки пространства шаблона.

  • Ключ во второй части представляет собой комбинацию опции -nи командыp(print ),который некоторые люди любят называть sed«режимом grep», и в основном эффекты, которые будут напечатаны только совпавшими и/или измененными строками. -nзапрещает печать любого вывода, а pпринудительно печатает совпадающие и/или измененные строки. Таким образом, вы избежите печати строк, которые были полностью пустыми. Так как \W\+ожидает по крайней мере один не -словесный символ, пустые строки отсутствуют. И начальные пробелы, которые могли бы соответствовать выражению, ранее превращались в пустые строки.

  • РЕДАКТИРОВАТЬ :Я забыл объяснить, что отсутствие команды pв первом выражении также является ключевым. В каждом выражении пространство шаблона обычно печатается, заставляя нас видеть каждую строку столько раз, сколько было выражений, которые ее печатали, с вариациями, если какое-либо из этих выражений также изменило данную строку. Однако, несмотря на то, что пространство шаблонов не печатается, оно переносится в последующие выражения в его измененной форме, что позволяет нам связывать выражения, которые работают с одним конвейером, который начинается с одной входной строки, при этом видя только вывод последнего выражения..

Если вам нравится рассматривать слова как последовательности не -пробельных символов, что ж... так оно и есть, но это определение охватывает гораздо больше, чем просто слова. Это не слова, это не -пробельные последовательности. Однако, если вы хотите сопоставить их и напечатать их в отдельных строках вместо слов, используйте:

sed -n -e 's/^\s*//' -e 's/\(\s\+\)/\n/gp' words.txt

Подход с заменой нулевого -байта

РЕДАКТИРОВАТЬ :Проблема строк с одним словом и отсутствующей новой строкой в ​​EOF, как указано @don _crissti, может быть решена с помощью следующей команды. Хотя он и не слишком длинный, помимо того, что он смехотворно хакерский, у него есть по крайней мере один недостаток, о котором я знаю :, а именно то, что он не работает для файла только с одной строкой, если эта единственная строка содержит несколько слов.Идея решить эту проблему состоит в том, чтобы добавить ветки, чтобы проверить, является ли последняя строка первой, еще больше усложнив программу (и отняв у меня еще больше времени :D ). Вот команда:

sed -rn 's/(\b|\W)+/\x0/g; s/^\x0//; s/\x0$//; s/\x0/\n/g; /^$/d; $! p; $ { s/$/\n/; P }'

Пояснение:

Команда работает в следующих проходах:

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

  • Затем из начала и конца каждой строки удаляется ноль -байтов.

  • Затем каждый промежуточный нулевой -байт заменяется новой строкой.

  • Любые полученные пустые строки удаляются из пространства шаблонов. Здесь нет пробелов -, только строки.

  • Если адрес текущего пространства шаблонов не является последним адресом (, то есть мы не находимся на последней строке ), мы просто печатаем строку.

  • В конце наших данных выполняем 2 команды:

    • Мы добавляем новую строку в конце текущего пространства шаблонов, чтобы иметь по крайней мере 1 завершающую новую строку, даже если исходные данные не заканчивались на нее.

    • Мы печатаем только до первой встроенной новой строки в нашем текущем пространстве шаблонов, которая имеет максимум 2 новые строки.

Кстати, самое простое решение этой проблемы, которое я видел, это:

grep -o '\w\+' words.txt

Или, если вам не нужно иметь дело со строками, начинающимися с пробела:

fmt -1 words.txt

1
27.01.2020, 20:32

Так как это должно быть sed, вот два (возможно 4 )решения:

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

s/[\n[:blank:]]\+/\n/g

Одна проблема заключается в том, чтобы применить это ко всему файлу, а другая — иметь дело с пустыми строками и требуемой последней новой строкой.

  • Считать весь файл в пространство шаблонов:
    Первое решение — прочитать весь файл в память и обработать его :

    .
    sed ':read;$!{N;bread};  s/[\n[:blank:]]\+/\n/g;   s/^\n//;  $a\' file
    

    Пояснение:

    :read;$!{N;bread};         Read the whole file into the pattern space.
    s/[\n[:blank:]]\+/\n/g;    convert all runs of spaces, tabs and newlines to newline.
    s/^\n*//;                  remove file initial newlines.
    $a\                        add a trailing newline (if missing).
    
  • Работа над каждой строкой (меньше памяти ).
    Альтернативой является обработка каждой строки отдельно, но тогда работа с пустыми строками, начальными и конечными символами новой строки становится сложной :

    .
    sed -E  ':read;$!N;s/[[:space:]]+/\n/g;  :print;s/^\n*//;/\n/{P;s/^[^\n]+//;bprint};$!bread;a\' file
    

    Пояснение:

    :read;                  label to read one (additional) line
    $!N;                    (except on last line) append a line to pattern space.
    s/[[:space:]]+/\n/g;    convert runs of white spaces to one newline.
    :print;                 label to print output.
    s/^\n*//;               remove leading newlines.
    /\n/bread;              if the pattern space has (at least) one newline.
    { 
        P;                  print (up to the first newline).
        s/^[^\n]+//;        remove what was printed.
        bprint;             loop to next part to be printed.
    }                       if the pattern space had no newlines:
    $!bread;                (except on last line) read one more line.
    a\'                     ensure a newline is printed on the last line.
    
  • Использовать два вызова sed.
    Большую часть сложности можно избежать, если делегировать удаление пустых строк второму вызову sed:

    sed -E  '$!N;s/[[:space:]]+/\n/g;l;P;D'  file   | sed '/^$/d;a\'
    
  • Используйте tr для преобразования новых строк в пробелы (все в одной строке)
    Также проще использовать tr для преобразования всех новых строк в один пробел,преобразование всего файла в одну (длинную )строку и последующая обработка с помощью sed:

    <file tr '\n' ' ' | sed -E 's/$/ /;s/[[:space:]]+/ /g;s/^ //;y/ /\n/'
    

Решения POSIXfied:

sed -Ee ':read' -e '$!{N;bread' -e '}' -e 's/[[:space:]]+/\
/g;l;s/^\n//;s/\n+$//;l'

sed -Ee  ':read' -e '$!N;s/[[:space:]]+/ /g;s/^ *//;s/ +$//;:print' -e '/ /{y/ /\n/;P;y/\n/ /;s/^[^ ]+ +//;bprint' -e '}' -e '$!bread' -e 's/ +$//' file

sed -Ee '$!N;s/[[:space:]]+/\
/g;P;D'  "${1-file}"   | sed '/^$/d'
0
27.01.2020, 20:32

Теги

Похожие вопросы