Могут ли команды tr быть закодированы, чтобы избежать нескольких tr процессов в конвейере?

У меня есть куча txt-файлов, я хотел бы выводить их с нижним, только буквенным и одним словом на строку, я могу сделать это с несколькими tr командами в конвейере вроде этого:

 tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n' 

Можно ли сделать это одним сканированием? Я мог бы написать программу на C, чтобы сделать это, но я чувствую, что есть способ сделать это, используя tr , sed , awk или perl .

3 Solutions collect form web for “Могут ли команды tr быть закодированы, чтобы избежать нескольких tr процессов в конвейере?”

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

 <doyle_sherlock_holmes.txt tr -d '[:punct:]' | tr '[:upper:] ' '[:lower:]\n' 

Два вызова tr , вероятно, будут быстрее, чем один вызов более сложных инструментов, но это очень зависит от размера ввода, от пропорций разных символов, от реализации tr и конкурирующих инструментов, от операционной системы, от количество ядер и т. д.

Вот несколько подходов:

  • GNU grep и tr : найти все слова и сделать их нижним регистром

     grep -Po '\w+' file | tr '[AZ]' '[az]' 
  • GNU grep и perl: как указано выше, но perl обрабатывает преобразование в нижний регистр

     grep -Po '\w+' file | perl -lne 'print lc()' 
  • perl: найти все алфавитные символы и напечатать их в нижнем регистре (спасибо @steeldriver):

     perl -lne 'print lc for /[az]+/ig' file 
  • sed: удалите все символы, которые не являются алфавитами или пробелами, замените все буквенные символы их нижестоящими версиями и замените все пробелы символами новой строки. Обратите внимание, что это предполагает, что все пробелы являются пробелами, без вкладок.

     sed 's/[^a-zA-Z ]\+//g;s/[a-zA-Z]\+/\L&/g; s/ \+/\n/g' file 

Да. Вы можете сделать это w / tr в локали ASCII (что для GNU tr любом случае является своеобразным видом) . Вы можете использовать классы POSIX, или вы можете ссылаться на байтовые значения каждого символа на восьмеричное число. Вы также можете разделить свои преобразования по диапазонам.

 LC_ALL=C tr '[:upper:]\0-\101\133-140\173-\377' '[:lower:][\n*]' <input 

Вышеприведенная команда преобразует все символы верхнего регистра в нижний регистр, полностью игнорирует строчные буквы и преобразует все остальные символы в новые строки. Конечно, тогда вы заканчиваете тонну пустых линий. В этом случае может оказаться полезным переключатель повторов tr -s quizze, но если вы используете его вместе с преобразованием [:upper:] to [:lower:] то вы также сжимаете символы верхнего регистра. Таким образом, по-прежнему требуется второй фильтр, например …

 LC... tr ... | tr -s \\n 

…или…

 LC... tr ... | grep . 

… и поэтому он становится намного менее удобным, чем делать …

 LC_ALL=C tr -sc '[:alpha:]' \\n <input | tr '[:upper:]' '[:lower:]' 

… который сжимает -c дополнение к алфавитным символам посредством последовательности в одну новую строку, а затем выполняет верхнее и нижнее преобразование на другой стороне трубы.

Это не значит, что диапазоны такого рода не полезны. Например:

 tr '\0-\377' '[1*25][2*25][3*25][4*25][5*25][6*25][7*25][8*25][9*25][0*]' </dev/random 

… может быть очень удобной, так как она преобразует входные байты во все цифры по расширенному спектру их значений. Не тратьте, не хотите, вы знаете.

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

 tr '\0-\377' '[A*64][B*64][C*64][D*64]' </dev/urandom | dd bs=32 cbs=8 conv=unblock,lcase count=1 dadbbdbd ddaaddab ddbadbaa bdbdcadd 

Поскольку dd может одновременно выполнять как unblock и преобразование lcase , возможно, даже удастся передать большую часть работы. Но это может быть действительно полезно, если вы можете точно предсказать количество байтов на слово – или, по крайней мере, можете заранее заполнить каждое слово пробелами до прогнозируемого количества байтов, потому что unblock ест конечные пробелы в конце каждого блока.

  • Что делает «текст» точно в Bash? Может ли он использоваться в Zsh?
  • Самый быстрый и самый основной способ заменить «\ r \ n» на «\ n» в файле?
  • Сделать статистику биграмм
  • Почему команда tr не читается из файла?
  • Является ли историческое поведение команды Unix V5 tr дополнением set2 отличным от того, что мы считаем сегодня «классическим» поведением System V (1983-1988)?
  • Как я могу распечатать все, кроме последних n символов в bash?
  • распечатать последнее поле из строки + альтернатива для awk
  • Debian wheezy update break tr команда
  • Замените несколько пробелов одним, используя только «tr»
  • как использовать tr для удаления восьмеричной последовательности символов?
  • tr аналог для символов Unicode?
  • Linux и Unix - лучшая ОС в мире.