Обработка текстов в *nix

Очень часто администраторам *nix-систем приходится выполнять различные выборки, сортировки, группировки неструктурированных данных. Благо система имеет уйму утилит для этого. Рассмотрим в примерах выборку определённых полей файла. Надо отобрать из файла данные размещённые в первой, пятой и шестой колонках файла /etc/passwd.

Существует множество решений, ниже приведены лишь несколько из них:

   1. cat /etc/passwd | awk -F: '{print $1" "$5" "$6}'
 
      ...
      avahi Avahi mDNS daemon,,, /var/run/avahi-daemon
      haldaemon Hardware abstraction layer,,, /home/haldaemon
      ...
 
   2. cat /etc/passwd | awk -F: '{print $1":"$5":"$6}'
 
      ...
      avahi:Avahi mDNS daemon,,,:/var/run/avahi-daemon
      haldaemon:Hardware abstraction layer,,,:/home/haldaemon
      ...
 
   3. cat /etc/passwd | cut -d":" -f1,5,6
 
      ...
      avahi:Avahi mDNS daemon,,,:/var/run/avahi-daemon
      haldaemon:Hardware abstraction layer,,,:/home/haldaemon
      ...
 
   4. cut -d":" -f1,5,6 /etc/passwd
 
      ...
      avahi:Avahi mDNS daemon,,,:/var/run/avahi-daemon
      haldaemon:Hardware abstraction layer,,,:/home/haldaemon
      ...

Чем отличаются друг от друга эти варианты?

Первые два варианта: 1 и 2, — используют cat и awk. Первая утилита выводит содержимое файла /etc/passwd, вторая отбирает необходимые поля. «-F:» указывает на то, что разделителем полей в потоке служит двоеточие. Обратный слэш () перед двоеточием предписывает читать двоеточие, как двоеточие и не пытаться обработать его, как спецсимвол. В общем-то, обратный слэш используется в данном случае для перестраховки. Обратите внимание, что в первом случае мы вывели поля (нумеруются начиная с 1), разделённые пробелом, а во втором — двоеточием. Если вам необходимо модифицировать вывод, используйте эту связку, если вам нужно просто вывести требуемые поля пользуйтесь вариантами три или четыре.

В третьем варианте используется связка cat и cut. Первый выводит, второй режет 🙂 Эту связку можно можифицировать так, как указано в варианте 4, так как cut может принимать на вход и поток (вариант три), и файл (вариант четыре). -d»:» — указывает считать разделителем полей двоеточие. Здесь разделитель указан в кавычках, поэтому использовать обратный слэш () нет необходимости. -f1,5,6 говорит о том, что нужно отобразить 1-ое, 5-ое и 6-ое поля. Имейте ввиду, что для cut порядок полей, пречисленных после -f, не имеет значения. Поля будут выводится так, как они расположены в файле. Другими словами, вы просто указываете какие поля вас интересуют, а не порядок вывода полей. Если вам необходимо изменить порядок полей, воспользуйтесь awk.Например, так:

cat /etc/passwd | awk -F: '{print $6" "$5" "$1}'
 
...
/var/run/avahi-daemon Avahi mDNS daemon,,, avahi
/home/haldaemon Hardware abstraction layer,,, haldaemon
...

Кроме того, awk также умеет получать данные не только из потока, но и напрямую из файла. Т.е. последний пример мы можем переписать так:

awk -F: '{print $6" "$5" "$1}' /etc/passwd
 
...
/var/run/avahi-daemon Avahi mDNS daemon,,, avahi
/home/haldaemon Hardware abstraction layer,,, haldaemon
...

Почему я чаще пользуюсь конструкцией «cat | awk» или «cat | cut»? Всё просто. Когда я пытаюсь отобрать поля, я не всегда помню их точное положение в файле. Тогда я делаю: cat /etc/passwd

Получаю полный список. После чего, уточнив нужные поля, нажимаю стрелочку вверх (в bash это вызов предыдущей команды) и дописываю | awk……..