Каждое слово на отдельной строке

У меня есть предложение вроде

Это, например,

Я хочу записать это в файл, чтобы каждое слово в этом предложении записывалось в отдельную строку.

Как это сделать в сценариях оболочки?

Ответ 1

Несколько способов сделать это, выбрать свой любимый!

echo "This is for example" | tr ' ' '\n' > example.txt

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

tr ' ' '\n' <<< "This is for example" > example.txt

Обозначение <<< используется с herestring

Или используйте sed вместо tr:

sed "s/ /\n/g" <<< "This is for example" > example.txt

Для еще большего количества альтернатив, проверьте ответы других пользователей =)

Ответ 2

$ echo "This is for example" | xargs -n1
This
is
for
example

Ответ 3

Попробуйте использовать:

string="This is for example"

printf '%s\n' $string > filename.txt

или воспользовавшись word -расщепление

string="This is for example"

for word in $string; do
    echo "$word"
done > filename.txt

Ответ 4

example="This is for example"
printf "%s\n" $example

Ответ 5

Попробуйте использовать:

str="This is for example"
echo -e ${str// /\\n} > file.out

Выход

> cat file.out 
This
is
for
example

Ответ 6

NB. Я написал это в нескольких черновиках, упрощающих регулярное выражение, так что, если есть какое-то несоответствие, возможно, почему.

Вы заботитесь о знаках препинания? Например, в некоторых вызовах вы можете увидеть, например, "слово", подобное (и т.д.), Точно в скобках. Или слово будет "круглые скобки". а не "круглые скобки". Если вы анализируете файл с правильными предложениями, это может быть проблемой, особенно если вы хотите отсортировать по слову или даже получить количество слов для каждого слова.

Есть способы справиться с этим, но есть некоторые предостережения и, безусловно, есть место для улучшения. Это происходит с числами, тире (в числах) и десятичных точках/точках (в числах). Возможно, наличие точного набора правил поможет решить эту проблему, но приведенные ниже примеры могут дать вам некоторые вещи для работы. Я сделал несколько надуманных входных примеров, чтобы продемонстрировать эти недостатки (или как вы хотите их назвать).

$ echo "This is an example sentence with punctuation marks and digits i.e. , . ; \! 7 8 9" | grep -o -E '\<[A-Za-z0-9.]*\>'
This
is
an
example
sentence
with
punctuation
marks
and
digits
i.e
7
8
9

Как вы можете видеть, то есть "ie" оказывается просто ie, а знаки препинания в противном случае не отображаются. Хорошо, но это оставляет такие вещи, как номера версий в виде major.minor.revision-release, например, 0.0.1-1; это тоже можно показать? Да:

$ echo "The current version is 0.0.1-1. The previous version was current from 2017-2018."|grep -o -E '\<[-A-Za-z0-9.]*\>'
The
current
version
is
0.0.1-1
The
previous
version
was
current
from
2017-2018

Обратите внимание, что предложения не заканчиваются с полной остановкой. Что произойдет, если вы добавите пробел между годами и тире? Вы не будете иметь черту, но каждый год будет на своей линии:

$ echo "2017 - 2018" | grep -o -E '\<[-A-Za-z0-9.]*\>'
2017
2018

Тогда возникает вопрос, если хотите - сами по себе быть посчитанными; по самой природе разделения слов у вас не будет лет в виде одной строки, если есть пробелы. Потому что это не слово само по себе, я бы подумал, что нет.

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

$ echo "The current version is 0.0.1-1. The previous version was current from 2017-2018."|grep -o -E '\<[A-Za-z]*\>'
The
current
version
is
The
previous
version
was
current
from

Если вы хотите иметь номера:

$ echo "The current version is 0.0.1-1. The previous version was current from 2017-2018."|grep -o -E '\<[A-Za-z0-9]*\>'
The
current
version
is
0
0
1
1
The
previous
version
was
current
from
2017
2018

Что касается "слов" с буквами и цифрами, то это еще одна вещь, которая может или не может быть рассмотрена, но демонстрирует вышесказанное:

$ echo "The current version is 0.0.1-1. test1."|grep -o -E '\<[A-Za-z0-9]*\>'
The
current
version
is
0
0
1
1
test1

Выводит их. Но следующее не (потому что это вообще не учитывает числа):

$ echo "The current version is 0.0.1-1. test1."|grep -o -E '\<[A-Za-z]*\>'
The
current
version
is

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

Я могу суммировать, как это работает, но только справедливо; Я слишком устал, чтобы даже думать о многом:

Как это работает?

Я объясню только вызов grep -o -E '\<[-A-Za-z0-9.]*\>' Но во многом он такой же в других (символ вертикальной черты/трубы в расширенном grep допускает более одного шаблона):

Опция -o предназначена только для печати совпадений, а не всей строки. -E предназначен для расширенного grep (с таким же успехом можно использовать egrep). Что касается самого регулярного выражения:

<\ И \> - границы слов (начинающиеся и заканчивающиеся соответственно - вы можете указать только одну, если хотите); Я считаю, что опция -w - это то же самое, что и указание обоих, но, возможно, вызов немного отличается (на самом деле я не знаю).

'\<[-A-Za-z0-9.]*\>' Говорит тире, заглавные и строчные буквы и точку ноль или более раз. Что касается того, почему тогда это превращается, например, в .eg, я в это время могу только сказать, что это - образец, но у меня нет способностей, чтобы рассмотреть это больше.

Бонусный скрипт для подсчета частоты слов

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "Usage: $(basename ${0}) <FILE> [FILE...]"
    exit 1
fi

for file do
    if [ -e "${file}" ]
    then
        echo "** ${file}: "
        grep -o -E '\<[-A-Za-z0-9.]*\>' "${file}"|sort | uniq -c | sort -rn
    else
    echo >&2 "${1}: file not found"
    continue
    fi
done

Пример:

$ cat example 
The current version is 0.0.1-1 but the previous version was non-existent.

This sentence contains an abbreviation i.e. e.g. (so actually two abbreviations).

This sentence has no numbers and no punctuation  
$ ./wordfreq example 
** example: 
   2 version
   2 sentence
   2 no
   2 This
   1 was
   1 two
   1 the
   1 so
   1 punctuation
   1 previous
   1 numbers
   1 non-existent
   1 is
   1 i.e
   1 has
   1 e.g
   1 current
   1 contains
   1 but
   1 and
   1 an
   1 actually
   1 abbreviations
   1 abbreviation
   1 The
   1 0.0.1-1

NB. Я не транслитерировал прописные буквы в строчные, поэтому слова "и" отображаются как разные слова. Если вы хотите, чтобы все они были в нижнем регистре, вы можете изменить вызов grep в сценарии, чтобы он передавался в tr перед сортировкой:

    grep -o -E '\<[-A-Za-z0-9.]*\>' "${file}"|tr '[A-Z]' '[a-z]'|sort | uniq -c | sort -rn

Да, и так как вы спросили, хотите ли вы записать его в файл, вы можете просто добавить его в командную строку (это для необработанного вызова):

> output_file

Для сценария вы бы использовали его так:

$ ./wordfreq file1 file2 file3 > output_file