Замените все пробелы символом разрыва строки / абзаца, чтобы составить список слов
Я пытаюсь составить список греческого текста, который мы переводим в классе. Я хочу заменить каждый символ пробела или табуляции знаком абзаца, чтобы каждое слово отображалось в отдельной строке. Кто-нибудь может дать мне команду sed и объяснить, что я делаю? Я до сих пор пытаюсь понять, что такое.
8 ответов
Для достаточно современных версий sed отредактируйте стандартный ввод, чтобы получить стандартный вывод с помощью
$ echo 'τέχνη βιβλίο γη κήπος' | sed -E -e 's/[[:blank:]]+/\n/g'
τέχνη
βιβλίο
γη
κήπος
Если ваши словарные слова находятся в файлах с именем lesson1
а также lesson2
, перенаправить стандартный вывод sed в файл all-vocab
с
sed -E -e 's/[[:blank:]]+/\n/g' lesson1 lesson2 > all-vocab
Что это означает:
- Класс персонажа
[[:blank:]]
соответствует либо одному пробелу, либо одному символу табуляции.- использование
[[:space:]]
вместо этого, чтобы соответствовать любому отдельному символу пробела (обычно пробел, табуляция, перевод строки, возврат каретки, подача формы и вертикальная табуляция). +
квантификатор означает совпадение с одним или несколькими предыдущими шаблонами.- Так
[[:blank:]]+
представляет собой последовательность из одного или нескольких символов, которые являются пробелами или табуляцией.
- использование
\n
в замене есть та новая строка, которую вы хотите./g
Модификатор в конце означает выполнение замены столько раз, сколько возможно, а не один раз.-E
опция говорит Sed использовать расширенный синтаксис регулярных выражений POSIX и, в частности, для этого случая+
квантор. Без-E
Ваша команда Sed становитсяsed -e 's/[[:blank:]]\+/\n/g'
, (Обратите внимание на использование\+
а не просто+
.)
Perl-совместимые регулярные выражения
Для тех, кто знаком с Perl-совместимыми регулярными выражениями и PCRE-совместимым sed, используйте \s+
чтобы соответствовать серии хотя бы одного пробела, как в
sed -E -e 's/\s+/\n/g' old > new
или же
sed -e 's/\s\+/\n/g' old > new
Эти команды читают ввод из файла old
и записать результат в файл с именем new
в текущем каталоге.
Максимальная портативность, максимальная грубость
Возвращаясь почти к любой версии sed начиная с Версии 7 Unix, вызов команды немного более барочный.
$ echo 'τέχνη βιβλίο γη κήπος' | sed -e 's/[ \t][ \t]*/\
/g'
τέχνη
βιβλίο
γη
κήπος
Заметки:
- Здесь мы даже не предполагаем существование скромного
+
квантификатор и имитировать его с помощью одного пробела или табуляции ([ \t]
) следуют ноль или более из них ([ \t]*
). - Точно так же, предполагая, что sed не понимает
\n
для новой строки мы должны дословно включить его в командную строку.\
и конец первой строки команды является маркером продолжения, который экранирует непосредственно следующую новую строку, а остальная часть команды находится на следующей строке.- Примечание: не должно быть никаких пробелов, предшествующих экранированной новой строке. То есть конец первой строки должен быть точно обратным слешем, за которым следует конец строки.
- Этот подверженный ошибкам процесс помогает понять, почему мир переместился на видимые символы, и вам нужно будет проявить некоторую осторожность при попытке выполнить команду с помощью функции копирования и вставки.
Обратите внимание на обратную косую черту и цитирование
Команды выше всех использовали одинарные кавычки (''
) вместо двойных кавычек (""
). Рассматривать:
$ echo '\\\\' "\\\\"
\\\\ \\
То есть оболочка применяет различные правила экранирования к строкам в одинарных кавычках по сравнению со строками в двойных кавычках. Как правило, вы хотите защитить все обратные слэши, встречающиеся в регулярных выражениях, одинарными кавычками.
Портативный способ сделать это:
sed -e 's/[ \t][ \t]*/\
/g'
Это фактическая новая строка между обратной косой чертой и косой чертой. Многие реализации sed не знают о \n
так что вам нужен буквальный перевод строки. Обратная косая черта перед новой строкой предотвращает недовольство sed новой строкой. (в сценариях sed команды обычно заканчиваются символами новой строки)
С GNU sed вы можете использовать \n
в подстановке и \s в регулярном выражении:
sed -e 's/\s\s*/\n/g'
GNU sed также поддерживает "расширенные" регулярные выражения (например, в стиле egrep, а не в стиле perl), если вы зададите ему флаг -r, так что вы можете использовать +
:
sed -r -e 's/\s+/\n/g'
Если это только для Linux, вы, вероятно, можете использовать команду GNU, но если вы хотите, чтобы это работало на системах с не-GNU sed (например, BSD, Mac OS-X), вы можете перейти с более портативный вариант.
Все перечисленные выше примеры для sed ломаются на той или иной платформе. Ни одна из них не работает с версией sed, поставляемой на Mac.
Тем не менее, регулярное выражение Perl работает одинаково на любом компьютере с установленным Perl:
perl -pe 's/\s+/\n/g' file.txt
Если вы хотите сохранить вывод:
perl -pe 's/\s+/\n/g' file.txt > newfile.txt
Если вы хотите только уникальные вхождения слов:
perl -pe 's/\s+/\n/g' file.txt | sort -u > newfile.txt
Это должно сделать работу:
sed -e 's/[ \t]+/\n/g'
[ \t]
означает пробел ИЛИ вкладку. Если вам нужен какой-либо вид пространства, вы также можете использовать \s
,
[ \t]+
означает столько пробелов ИЛИ вкладок, сколько вы хотите (но не менее одной)
s/x/y/
означает заменить шаблон х на у (здесь \n
это новая линия)
g
в конце означает, что вы должны повторять столько раз, сколько это происходит в каждой строке.
Вы также можете сделать это с xargs
:
cat old | xargs -n1 > new
или же
xargs -n1 < old > new
Вы могли бы использовать POSIX [[:blank:]]
соответствовать горизонтальному пробелу.
sed 's/[[:blank:]]\+/\n/g' file
или вы можете использовать [[:space:]]
вместо [[:blank:]]
также.
Пример:
$ echo 'this is a sentence' | sed 's/[[:blank:]]\+/\n/g'
this
is
a
sentence