У меня есть куча TXT-файлов, я хотел бы вывести их в нижнем регистре, только в алфавитном порядке и по одному слову в строке, я могу сделать это с помощью нескольких tr
команд в конвейере, например:
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
Возможно ли сделать это за один просмотр? Я мог бы написать программу C , чтобы сделать это, но я чувствую, что есть способ сделать это с помощью tr
, sed
, awk
или perl
.
Ответы:
Вы можете объединить несколько переводов (за исключением сложных случаев, связанных с перекрывающимися локал-зависимыми наборами), но вы не можете объединить удаление с переводом.
Два вызова
tr
, скорее всего, будут быстрее, чем один вызов более сложных инструментов, но это очень зависит от размера ввода, от пропорций различных символов, от реализацииtr
и конкурирующих инструментов, от операционной системы, от числа ядер и т. д.источник
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
получаетa\na\na'
, и преобразование for... '[:lower:]\n'
может вообще не делать вообще ничего'[:punct:]'
- некоторыеtr
усекают set1 до совпадения 2, а другие подразумевают[\n*]
. Лучше просто использовать диапазон там.Вот несколько подходов:
GNU
grep
иtr
: найти все слова и сделать их строчнымиGNU grep и perl: как указано выше, но perl обрабатывает преобразование в нижний регистр
perl: найти все буквенные символы и вывести их в нижнем регистре (спасибо @steeldriver):
sed: удалите все символы, которые не являются буквенными или пробелами, замените все буквенные символы их строчными версиями и замените все пробелы символами новой строки. Обратите внимание, что это предполагает, что все пробелы - это пробелы, а не табуляции.
источник
perl -lne 'print lc for /[[:alpha:]]+/g'
также работать? или это плохой стиль? (Я новичок в Perl и пытаюсь учиться!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
можешь сделать\w
сейчас? Прохладно!sed
«s-z
эро разграничить переключатель - это циклы через\0NUL
S , а не переводы строк. Довольно круто, когда ты делаешь что-то вродеtar -c . | tr -s \\0 | sed -z ...
- но довольно медленно.Да. Вы можете сделать это с
tr
помощью локали ASCII (которая вtr
любом случае является для GNU своего рода единственной задачей) . Вы можете использовать классы POSIX или ссылаться на байтовые значения каждого символа по восьмеричному числу. Вы также можете разделить их преобразования по диапазонам.Приведенная выше команда преобразует все заглавные буквы в строчные, полностью игнорирует строчные буквы и преобразует все остальные символы в символы новой строки. Конечно, тогда вы получите тонны пустых строк. Переключатель
tr
-s
queeze repeat может быть полезен в этом случае, но если вы используете его вместе[:upper:]
с[:lower:]
преобразованием to, то вы также сжимаете заглавные буквы. Таким образом, он все еще требует второго фильтра, как ......или...
... и так получается гораздо менее удобно, чем делать ...
... который сжимает
-c
последовательность алфавитных символов по порядку в одну новую строку, а затем выполняет преобразование сверху вниз на другой стороне трубы.Нельзя сказать, что диапазоны такого рода бесполезны. Вещи как:
... может быть очень удобно, так как он преобразует входные байты во все цифры по расширенному спектру их значений. Не тратьте, не хотите, вы знаете.
Другой способ сделать преобразование может включать
dd
.Поскольку
dd
можно одновременно выполнять преобразованияunblock
иlcase
преобразования, возможно, даже удастся передать большую часть работы. Но это может быть действительно полезным, только если вы можете точно предсказать количество байтов на слово - или, по крайней мере, можете заранее заполнить каждое слово пробелами до предсказуемого количества байтов, потому чтоunblock
съедает конечные пробелы в конце каждого блока.источник
dd
участие :)