Інструменти для перекладу і управління текстом в UNIX (исходники), Unix, Операційні системи, статті

Своїм походженням UNIX® зобов'язаний простий обробки текстів, і середовище його командного рядка залишається одним з найпотужніших доступних інструментів. Комбінуючи ряд простих команд, що забезпечують складні перетворення тексту, ви можете створити за допомогою доступних в UNIX коштів майже будь-який потрібний вам інструмент обробки тексту.

Введення


На зорі історії UNIX ® люди, які працювали з цією новою операційною системою, швидко знайшли нішу, яку змогли заповнити; людям в університетах була потрібна відповідна середовище обробки текстів. Через швидкості обробки даних та кількості пам'яті в комп'ютерах в ті дні програми повинні були бути невеликими і відносно простими. Це призвело до знаменитої філософії проектування UNIX: "набір засобів, що працюють спільно над одним завданням. "За допомогою комбінування декількох невеликих, але потужних інструментів обробки тексту в канали UNIX pipes, текст може бути перетворений і оброблений незліченним числом способів.


У цій статті ви можете коротко ознайомитися з витягом тексту з файлів і програм, з простими транслітерації за допомогою команди tr і складними операціями пошуку і заміни за допомогою команди sed. Потім ви виконаєте все те ж саме знову за допомогою мови програмування і написання скриптів Perl, так що ви побачите, яким чином Perl може служити потужної заміною як команди tr, Так і sed.


Перш, ніж почати


Якщо ви хочете наслідувати приклади з цієї статті і експериментувати з ними, переконайтеся, що ви отримали доступ до середовища командного рядка UNIX. Це може бути здійснено на вашій локальній машині через емулятор терміналу (часто званий Terminal на сучасних робочих столах; якщо ви занадто звикли використовувати Windows ®, добре підійде Cygwin), або на віддаленій системі через SSH.


Синтаксис оболонки, використаний тут в прикладах, підходить до GNU Bash; ласка, з'ясуйте в керівництві по вашій оболонці особливий синтаксис, який вам потрібно (або подумайте над тим, щоб переключитися в Bash, як я вважаю).


Як домогтися, щоб текст розвернувся


Перш ніж почати керувати текстом за допомогою декількох текстових утиліт з усього різноманіття UNIX, вам буде потрібно дізнатися, як дістатися до якого б то не було тексту. І перш ніж це зробити, вам потрібно освоїти потоки стандартного вводу / виводу UNIX.


Стандартна бібліотека C (і тому кожна програма UNIX) визначила три стандартних потоки: введення, виведення, і повідомлення про помилку. Їх іноді називають stdin, stdout і stderr слідом за глобальними змінними, якими вони представлені в кожній програмі на C.


Коли ви перенаправляє висновок програми в файл за допомогою оператора> в оболонці, ви посилаєте потік її стандартного виводу (stdout) в файл. Наприклад: ls > this-dir посилає висновок ls у файл з ім'ям this-dir.


Коли ви перенаправляє введення програми з файлу за допомогою оператора <в оболонці, ви витягаєте вміст файлу в потік її стандартного вводу (stdin). Наприклад: sort < this-dir зчитує вміст файлу з ім'ям this-dir і надає його як введення команді sort.


Інший загальний оператор для перенаправлення стандартних потоків – це оператор / (pipe), який зв'язує потік стандартного висновку програми зліва з потоком стандартного введення програми справа. Наприклад: ls / sort робить те ж, що й попередні два приклади, не вимагаючи тимчасового файлу; висновок ls проходить безпосередньо через команду sort.


Якщо ви були уважні, то, можливо, помітили, що потік стандартних повідомлень про помилку (stderr) не представлений в жодному з цих прикладів. Як і потік стандартного висновку, stderr може бути перенаправлений у файл або іншу програму, але вам потрібно буде повідомити оболонці, що ви хочете працювати з stderr замість stdout.


Перенаправляти потоки стандартних повідомлень про помилку в файл за допомогою оператора 2>. Найчастіше ви це будете бачити, працюючи з командами, які виводять змістовні повідомлення про помилку, такими як інструмент make, використовуваний для складання програм під UNIX: make 2> build-errors.


Ця команда запускає make і посилає будь-які повідомлення про помилки в файл build-errors. Подібним чином ви б використовували 2 /, щоб перенаправити stderr в іншу програму.


Якщо вас цікавлять непріукрашенние деталі, в інших потоків також є номери, хоча вони майже ніколи не використовуються (0 – це стандартне введення, а 1 – стандартний висновок), за винятком одного напрочуд звичайним оператором. У прикладі, наведеному в лістингу 1, оператор 2> & 1 прив'язує потік стандартних повідомлень про помилку до потоку стандартного виводу. У комбінації з оператором> ви отримаєте stderr і stdout в одному і тому ж файлі.


Лістинг 1. Як прив'язати потік стандартних повідомлень про помилку до потоку стандартного висновку





make > build-output 2>&1


Нарешті, команди


Є дві стандартні команди UNIX, які часто використовують для породження деякого текстового виводу: cat і echo.


Команда cat зчитує кожен з файлів, зазначених в її аргументах, і виводить вміст файлів в stdout. Команда echo виводить у stdout свої аргументи. Ви будете часто їх бачити в якості частині більш складної командного pipe-рядка (див. Лістинг 2.


Лістинг 2. Як використовувати cat і echo







cat file1 file2 … filen
echo arguments…


Але що, якщо ви хочете отримати тільки першу частину файлу, або останню? Є два варіанти cat під назвами head і tail (див. Лістинг 3), які зроблять те, що ви хочете, виводячи перші або останні десять рядків, відповідно (для обох команд ви можете вказати іншу кількість рядків за допомогою опції-n).


Лістинг 3. Як використовувати head і tail







head file1 file2 … filen
tail file1 file2 … filen


У команди tail є інша зручна опція -f (Англ. follow, супроводжувати). Вона повідомляє tail друкувати останні десять рядків зазначеного файлу, але, замість того, щоб завершуватися, вона чекає, що у файлі з'явиться більше тексту, і друкує його, як тільки він з'являється. Це можна використовувати, щоб супроводжувати висновок в журнал помилок, наприклад, щоб побачити, які помилки з'являються в момент, коли вони записуються в журнал.


Як перекладати текст


Тепер, коли ви знаєте, принаймні, п'ять різних способів породження тексту, розглянемо те, як робляться деякі прості його в ньому.


Команда tr дозволяє вам перекладати символи з одного набору в відповідні символи з іншого. Розглянемо кілька прикладів (Лістинг 4), щоб побачити, як це працює.


Лістинг 4. Як використовувати tr, щоб переводити символи





echo “a test” / tr t p
echo “a test” / tr aest 1234
echo “a test” / tr -d t
echo “a test” / tr “[:lower:]” “[:upper:]”


Поглянувши на виведення цих команд (див. Лістинг 5), ви отримаєте ключ до того, як працює tr (Підказка: це пряма заміна символів з першого набору відповідними символами з другого).


Лістинг 5. Що зробила tr?





chrish@dhcp3 [199]$ echo “a test” / tr t p
a pesp

chrish@dhcp3 [200]$ echo “a test” / tr aest 1234
1 4234

chrish@dhcp3 [201]$ echo “a test” / tr -d t
a es

chrish@dhcp3 [202]$ echo “a test” / tr “[:lower:]” “[:upper:]”
A TEST



Перший і другий приклади досить прості: один символ замінюється іншим. Третій приклад, з опцією -d (Англ. delete, видалення), повністю видаляє вказані символи з висновку. Це часто використовується для видалення символів повернення каретки з текстових файлів DOS, щоб перетворити їх на текстові файли UNIX (Див. Лістинг 6). Нарешті, в останньому прикладі застосовуються класи символів (ці імена в [::]), щоб конвертувати всі букви в нижньому регістрі в літери у верхньому регістрі. Класи символів стандарту інтерфейсу переносимої операційної системи Portable Operating System Interface (стандарту POSIX) включають в себе:



Лістинг 6. Перетворення текстових файлів DOS в текстові файли UNIX





tr -d ”
” < input_dos_file.txt > output_unix_file.txt


Хоча команда tr приймає команди середовища локалі C (подивіться man locale, щоб отримати про них більше інформації), не чекайте від неї, що вона зробить щось відчутне з документами в кодуванні UTF-8, – наприклад, зможе замінити символи з діакрітікамі в нижньому регістрі відповідними символами у верхньому регістрі. Команда tr найкраще працює з ASCII та іншими стандартними локалях C.


Складний пошук і заміна за допомогою sed


Можливості Односимвольний заміни (або видалення), що надаються командою tr, Великі в особливих випадках, але не дуже гнучкі. Що, якщо вам потрібно замінити одне слово іншим, або ряд прогалин і символів табуляції одним пропуском?


На щастя, у вашому розпорядженні команда sed (Англ. Stream EDitor, редактор потоку), яка забезпечує потужний пошук збігів і заміну за допомогою регулярних виразів. Регулярні вирази – це складні вказівки шаблонів, утворені за допомогою будівельних блоків, які в підсумку виглядають найбільше схожими на перешкоди в модемі у міру того, як шаблон ускладнюється. Детальне керівництво за регулярними виразами – це матеріал для іншої статті, а тут ви коротко ознайомитеся з деякими зручними для використання в sed шаблонами.


Основний формат команди sed показаний в лістингу 7. Шаблон (pattern) – це регулярний вираз, що використовується для пошуку збігів у вхідному потоці (зазвичай або перенаправленням з іншої програми, або з текстового файлу), а заміна (Replacement) – це текст, який слід вставити замість тексту, що співпала з шаблоном. Прапори (flags) – це одиночні символи, які контролюють поведінку цієї підстановки. Самий часто використовуваний прапор – Це g (Застосувати заміну до всіх непересічним екземплярів, які співпадають з шаблоном, замість того, щоб застосувати її тільки до першого збігу).


Шаблон і заміна можуть бути практично що завгодно, і вони не повинні бути в одно-однозначним дотриманням, як це відбувається з командою tr.


Listing 7. Команда sed





sed -e s/pattern/replacement/flags


Найпростіший шаблон – це просто рядок з одного або декількох символів. У лістингу 8, наприклад, одне слово замінюється іншим.


Лістинг 8. Найпростіше регулярний вираз





chrish @ dhcp3 [334] $ echo "Replace one word" / sed -es/one/another /
Replace another word


Ви можете поставити один або декілька символів у квадратні дужки, щоб створити безліч; будь-який символ з цієї безлічі співпаде. Замінимо всі голосні на символи підкреслення (див. Лістинг 9).


Лістинг 9. Пошук збігів елемента множини





chrish @ dhcp3 [338] $ echo "This is a test" / sed-es / [aeiouy] / _ / g
Th_s _s _ t_st


Зверніть увагу на використання прапора g, Щоб застосувати шаблон / заміну до кожного збігом замість просто першого.


Команда sed також враховує іменовані класи символів, які підтримує команда tr; Вони визначені в POSIX, але тут застосовується інший синтаксис. Лістинг 10 показує вам, як замінювати будь пробіл (знаки табуляції, пробіли і т.д.):


Лістинг 10. Пошук збігів елемента іменованого класу символів





chrish@dhcp3 [345]$ echo -e “hello there”
hello there
chrish @ dhcp3 [346] $ echo-e "hello there" / sed-e "s / [[: space :]]/, /"
hello, there


Прапор -e команди echo вказує їй розширювати escaped-символи стилю C; в даному випадку він перетворить на знак табуляції для вас.


Ви також можете використовувати символ "." (Точка) для пошуку відповідностей будь-якого одиночного символу. Це дійсно зручно, коли ви працюєте з даними, які не характеризуються різноманітністю, або з даними, в яких зустрічаються спеціальні символи, які буде складно зробити escaped-символами. Наприклад, я часто застосовую ., Коли я шукаю збіги лапок, тому мені не потрібно робити лапки escaped-символами в оболонці. У лістингу 11 показаний випадок, коли, застосовуючи цей шаблон, користувач, можливо, створив нове регулярне вираз.


Лістинг 11. Це, ймовірно, не те, що ви хотіли





chrish@dhcp3 [339]$ echo “This is a test” / sed -e s/./_/g
______________


Тепер, коли саме основне ви вже побачили, розглянемо кілька додаткових модифікаторів шаблонів; тепер ви станете також використовувати опцію -E замість -e, Щоб користуватися вдосконаленими регулярними виразами. Символ ? позначає пошук нуля або одного відповідності попереднього елементу шаблону; символ * означає пошук нуля або більше відповідностей попереднього йому елементу. Символ + позначає пошук одного або декількох відповідностей попереднього елементу. Символ ^ відповідає початку рядка, а $ – Кінця. Це можна побачити у дії, як показано в лістингу 12.


Лістинг 12. Множинні відповідності в дії





chrish@dhcp3 [356]$ echo “hellooooo” / sed -E “s/o?$/_/g”
helloooo_
chrish@dhcp3 [357]$ echo “hellooooo” / sed -E “s/o*$/_/g”
hell_
chrish@dhcp3 [358]$ echo “hellooooo” / sed -E “s/o+$/_/g”
hell_


Якщо ви поставите елементи шаблону в круглі дужки, то зможете використовувати знайдені збіги в рядку заміни. Вони називаються групами; завдяки ним пошук регулярних виразів знаходить високу ефективність, але читаність вираження в істотному ступені може. Наприклад, в лістингу 13 шукається один або декілька символів l (Ель), за якими ідуть нуль або декілька символів o. Вони замінюються вмістом другої групи, за яким слідує перша, тобто, насправді, вони міняються місцями. Зверніть увагу, що на групи слід вказувати за допомогою бекслеші з номером групи в шаблоні.


Listing 13. Match groups





chrish @ dhcp3 [361] $ echo "hellooooo" / sed-E "s / (l +) (o *) $ / 21 / g"
heoooooll


Можна також здійснювати пошук відповідностей спеціальному кількістю повторень шаблону, вказуючи цю кількість у фігурних дужках. Наприклад, шаблоном o{2} будуть відповідати два (і тільки два) символу o.


Так, і останнє: будь-який з цих спеціальних символів можна використовувати в шаблоні в буквальному сенсі (тобто, сам по собі), роблячи його escaped-символом за допомогою символу.


Putting it together


Тепер, коли ви зіткнулися з кількома дуже простими регулярними виразами, ми можемо перейти до більш корисним. Працюючи з виведенням ls -l (Довгий список файлів), ви можете отримати інформацію про права доступу, розмір та назву. У лістингу 14 наведено приклад виведення ls -l для вашої подальшої роботи.


Лістинг 14. Типовий висновок ls-l





chrish@dhcp3 [365]$ ls -l / tail
drwx—— 3 chrish wheel 102 Jun 14 21:38 gsrvdir501
drwxr-xr-x 2 chrish wheel 68 Jun 16 16:01 hsperfdata_chrish
drwxr-xr-x 3 root wheel 102 Jun 14 23:38 hsperfdata_root
-rw-r–r– 1 root wheel 531 Jun 14 10:17
illustrator_activation.plist
-Rw-r – r – 1 root wheel 531 Jun 14 10:10 indesign_activation.plist
-Rw ——- 1 nobody wheel 24 Jun 16 16:01 objc_sharing_ppc_4294967294
-Rw ——- 1 chrish wheel 132 Jun 16 23:50 objc_sharing_ppc_501
-Rw ——- 1 security wheel 24 Jun 16 10:04 objc_sharing_ppc_92
-Rw-r – r – 1 root wheel 531 Jun 14 10:05 photoshop_activation.plist
-Rw-r – r – 1 root wheel 928 Jun 14 10:17 serialinfo.plist


Як ви можете помітити, тут є сім колонок:


Створимо кілька регулярних виразів для виділення вмісту кожної з них:


У проміжках вам доведеться об'єднати всі ці шаблони записом [[:space:]]+, Інакше ви не знаєте, розділені чи колонки пробілами, знаками табуляції, або ж їх комбінаціями. Також ви захочете помістити права доступу, розмір і ім'я в групи, щоб мати можливість використовувати їх у рядку заміни. Як видно з лістингу 15, регулярні вирази швидко стає важко читати.


Лістинг 15. Підсумкове регулярний вираз. Прикрийте очі!





(. ([R-] [w-] [x-]) {3 })[[: space :]]+[[: digit :]]+[[: space :]]+([ A-Za- z0-9_-.]
+[[:space:]]+){2}([[:digit:]]+)[[:space:]]+.{3} [0-9 ]{2} [0-9
][0-9]:[0-9][0-9][[:space:]]+(.+)$


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



  1. Весь блок прав доступу
  2. Остання виділена група rwx в блоці прав доступу
  3. Група (останній виявлений елемент в частині шаблону, що відповідає за власника / групу)
  4. Розмір
  5. Ім'я

У лістингу 16, висновок ls -l замінюється так, що в підсумку показує ім'я файлу, права доступу і розмір.


Лістинг 16. Перекомпоновані висновок





chrish@dhcp3 [382]$ ls -l / tail / sed -E
"S /(.([ r-] [w-] [x-]) {3 })[[: space :]]+[[: digit :]]+[[: space :]]+([ A -Za-z0-9_-.
]+[[: Space :]]+){ 2 }([[: digit :]]+)[[: space :]]+.{ 3} [0-9] {2} [0-9
][0-9]:[0-9][0-9][[:space:]]+(.+)$/5 (1) has 4 bytes of data/”
gsrvdir501 (drwx——) has 102 bytes of data
hsperfdata_chrish (drwxr-xr-x) has 68 bytes of data
hsperfdata_root (drwxr-xr-x) has 102 bytes of data
illustrator_activation.plist (-rw-r–r–) has 531 bytes of data
indesign_activation.plist (-rw-r–r–) has 531 bytes of data
objc_sharing_ppc_4294967294 (-rw——-) has 24 bytes of data
objc_sharing_ppc_501 (-rw——-) has 132 bytes of data
objc_sharing_ppc_92 (-rw——-) has 24 bytes of data
photoshop_activation.plist (-rw-r–r–) has 531 bytes of data
serialinfo.plist (-rw-r–r–) has 928 bytes of data


Перемога! Ви повністю змінили висновок.


Як це зробити за допомогою Perl


Мова програмування і написання скриптів Perl часто застосовується як надзвичайно потужна заміна командам tr і sed, На які ви тільки що дивилися. Коротка програма на Perl, часто вводиться безпосередньо з командного рядка, може іноді зробити більше, ніж еквівалентна рядок команди tr або sed.


Опція Perl -p вказує йому обробляти кожен рядок з стандартного вводу і друкувати результати на стандартний вивід. Опція -e дозволяє вказати вираз на Perl (насправді, програму) у командному рядку.


У лістингу 17 показано, як дублювати приклади з лістингу 5 при допомоги Perl.


Лістинг 17. Як використовувати Perl для вирішення завдань команди tr





chrish@dhcp3 [248]$ echo a test / perl -p -e “tr/t/p/;”
a pesp

chrish@dhcp3 [249]$ echo a test / perl -p -e “tr/aest/1234/;”
1 4234

chrish@dhcp3 [250]$ echo a test / perl -p -e “tr/t//d;”
a es

chrish@dhcp3 [251]$ echo a test / perl -p -e “tr/a-z/A-Z/;”
A TEST



Вираз Perl tr має злегка іншим синтаксисом, більш схожим на вирази пошуку та заміни sed. Також зверніть увагу, що в останньому прикладі символи верхнього та нижнього регістрів вказані за допомогою діапазонів.


Підтримка регулярних виразів в Perl чудова, і всі наведені вище приклади використання sed будуть працювати як вірні вирази Perl. У лістингу 18 Показати приклад з ls -l з лістингу 16 на Perl; ніде, крім синтаксису рядка команди Perl, не треба було ніяких змін.


Лістинг 18. Перебудова виведення ls за допомогою Perl





chrish@dhcp3 [384]$ ls -l / tail / perl -p -e
"S /(.([ r-] [w-] [x-]) {3 })[[: space :]]+[[: digit :]]+[[: space :]]+([ A -Za-z0-9_-.]
+[[:space:]]+){2}([[:digit:]]+)[[:space:]]+.{3} [0-9 ]{2} [0-9
][0-9]:[0-9][0-9][[:space:]]+(.+)$/5 (1) has 4 bytes of data/”
gsrvdir501 (drwx——) has 102 bytes of data
hsperfdata_chrish (drwxr-xr-x) has 68 bytes of data
hsperfdata_root (drwxr-xr-x) has 102 bytes of data
illustrator_activation.plist (-rw-r–r–) has 531 bytes of data
indesign_activation.plist (-rw-r–r–) has 531 bytes of data
objc_sharing_ppc_4294967294 (-rw——-) has 24 bytes of data
objc_sharing_ppc_501 (-rw——-) has 132 bytes of data
objc_sharing_ppc_92 (-rw——-) has 24 bytes of data
photoshop_activation.plist (-rw-r–r–) has 531 bytes of data
serialinfo.plist (-rw-r–r–) has 928 bytes of data


Чудово в цьому те, що ви можете відточувати ваші регулярні вирази як за допомогою sed, Так і Perl, і все одно використовувати їх в системах, в яких доступний або тільки один з них, або тільки інший. А в Perl у вашому розпорядженні повний набір програмних конструкцій, якими ви можете скористатися, здійснюючи навіть більш складну обробку тексту.


Резюме


Використовуючи потужні інструменти, такі як sed і Perl, і магічну силу регулярних виразів, можна просто вирішувати складні завдання обробки тексту безпосередньо з командного рядка UNIX. Це дозволяє ефективно комбінувати кілька команд, щоб домогтися правильного вирішення ваших завдань обробки тексту.


 


Про автора










 
 

Кріс Херборт (Chris Herborth)вже більше 10 років пише про операційні системи і програмуванні. Він вигравав нагороди як старший технічний письменник. Якщо він не грає з сином Алексом або просто проводить час з дружиною, Кріс присвячує свій вільний час написання статей і дослідженню відео ігор (тобто, грі).

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*