П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 178178 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 75633 раз(а).

Учебник HTML.
Просмотров 74104 раз(а).

Руководство по PHP5.
Просмотров 45039 раз(а).

Хостинг через призму DNS.
Просмотров 51972 раз(а).

Подборка текстов стандартных документов.
Просмотров 45134 раз(а).

Учебник PHP - Самоучитель
Просмотров 51367 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 51821 раз(а).

Внешние атаки...
Просмотров 41950 раз(а).

Учебник PHP.
Просмотров 37302 раз(а).

SSI в примерах.
Просмотров 27859 раз(а).



 
 
| Добавить в избранное | Сделать стартовой | Помощь





Руководство пользователя для GNU Awk

16. Практические awk-программы

16.1 Переизобретение колеса для забавы и пользы

16.1.1 Вырезание полей и колонок

Утилита cut выделяет или "вырезает" символы или поля из их стандартного ввода и посылает в стандартный вывод. cut может вырезать или список символов или список полей. По умолчанию поля разделяются символами tab, но вы можете указать в параметре командной строки другой символ как разделитель полей. В cut определение полей менее общее чем в awk. cut может только извлечь регистрационное имя зарегистрированного пользователя из входа who. Например, следующий конвейер генерирует отсортированный единый список работающих пользователей:


who -- cut -c1-8 -- sort -- uniq

Параметры для cut следующие: -c list

Использует list как список символов для вырезания (to cut out). Элементы в списке могут разделяться запятыми, а диапазоны символов могут разделяться символами минуса. Список `1-8,15,22-35' содержит символы от 1 до 8, 15 и от 22 до 35.

-f list

Использует list как список полей для вырезки.

-d delim

Использует delim как символ-разделитель полей вместо tab

-s

Подавляет печать строк, не содержащих разделителей полей.

awk-реализация cut использует библиотечную функцию getopt (см. раздел 15.10 [Обработка параметров командной строки], стр. 186), библиотечную функцию join (см. раздел 15.6 [Соединение элементов массива в цепочку], стр. 176).

Программа начинается с комментария, описывающего параметры и функцию usage, которая печатает сообщение и прекращает работу. usage вызывается, если обнаружены неверные аргументы.

# cut.awk --- реализация cut в awk
# Arnold Robbins, arnold@gnu.org, Public Domain 
# May 1993
# Параметры: 
# -f list Cut fields 
# -d c Символ разделитель полей
# -c list Cut characters 
# # -s Подавляет строки без символов-разделителей
function usage( e1, e2) -
e1 = "usage: cut [-f list] [-d c] [-s] [files...]"
e2 = "usage: cut [-c list] [files...]" print e1 ? "/dev/stderr"
print e2 ? "/dev/stderr" exit 1 ""

Переменные e1 и e2 используются для удобного расположения данных на странице.

Долее идет правило BEGIN, которое анализирует параметры командной строки. Оно заносит в FS один символ tab, разделитель полей по умолчанию. Разделитель выходных полей устанавливается тот же что и на входе. Затем используется getopt для анализа параметров в командной строке. Одна из переменных by.fields или by.chars устанавливается в true, для указания, что обработка будет идти по полям или по символам соответственно. При вырезке по символам разделитель выходных полей устанавливается в пустую цепочку.

BEGIN " -
FS = ""t" # по умолчанию  OFS = FS
while ((c = getopt(ARGC, ARGV, "sf:c:d:")) != -1) -
if (c == "f") -
by.fields = 1 fieldlist = Optarg
"" else if (c == "c") -
by.chars = 1 fieldlist = Optarg OFS = "" "" else if (c == "d") -
if (length(Optarg) ? 1) -
printf("Using first character of %s" " "
for delimiter"n", Optarg) ? "/dev/stderr" Optarg = substr(Optarg, 1, 1) ""
FS = Optarg OFS = FS if (FS == " ") # отмена семантики awk
FS = "[ ]" "" else if (c == "s")
suppress++ else
usage() ""
for (i = 1; i ! Optind; i++)
ARGV[i] = ""

особый случай составляет пробел как разделитель полей. Использование " " (один пробел) как значение FS неправильно--awk будет разделять поля группами пробелов, tab и/или newlines, а мы хотим разделения одним пробелом. Заметим также, что после конца работы getopt мы должны очистить все элементы ARGV от первого до Optind, чтобы awk не пыталась обработать параметры командной строками как имена файлов.

После окончания действий над параметрами командной строки, программа проверяет, что параметры имеют смысл. Только один из `-c' и `-f' должен быть указан, и оба требуют список полей. Затем вызывается или set.fieldlist или set.charlist для выделения списка полей или символов.

if (by.fields && by.chars)
usage()
if (by.fields == 0 && by.chars == 0)
by.fields = 1 # default
if (fieldlist == "") -
print "cut: needs list for -c or -f" ? "/dev/stderr" exit 1 ""
if (by.fields)
set.fieldlist() else
set.charlist() ""

Пусть будет set.fieldlist. Тогда сначала список полей расщепляется по запятым в компоненты массива. Затем, для каждого элемента массива, проверяется, что это действительно диапазон, и если так, то он откладывается в сторону. Диапазон проверяется, чтоб быть уверенным, что первое число меньше второго. Каждое число в списке добавляется в массив flist, в котором просто собираются поля для печати. Используется нормальное разделение полей. Программа оставляет за awk разделение полей при печати.

function set.fieldlist( n, m, i, j, k, f, g) -
n = split(fieldlist, f, ",") j = 1 
# index in flist for (i = 1; i != n; i++) -
if (index(f[i], "-") != 0) - 
# a range
m = split(f[i], g, "-") if (m != 2 ---- g[1] ?= g[2]) -
printf("bad field list: %s"n",
f[i]) ? "/dev/stderr" exit 1 "" for (k = g[1]; k != g[2]; k++)
flist[j++] = k "" else
flist[j++] = f[i] "" nfields = j - 1 ""

Функция set.charlist сложнее чем set.fieldlist. Здесь идея состоит в использовании gawk-переменной FIELDWIDTHS (см. раздел 5.6 [Чтение данных фиксированной ширины], стр. 49), где описывается ввод с постоянной шириной. При использовании списка символов мы точно это и имеем.

Установка FIELDWIDTHS более сложна, чем просто перечисление полей, которые должны быть напечатаны. Мы должны следить за полями для печати и также за промежуточными символами, которые должны быть пропущены. Например, предположим, вы ищете символы от 1 до 9, 15, и от 222 до 35. Вы должны использовать `-c 1-8,15,22-35'. Необходимое значение для FIELDWIDTHS будет "8 6 1 6 14". Это дает нам пять полей, и должны быть напечатаны $1, $3 и $5. Промежуточные поля есть "заполнители", мусор между нужными данными.

flist перечисляет поля для печати, а t следит за полным списком полей, включая поля-заполнители.

function set.charlist( field, i, j, f, g, t,
filler, last, len) -
field = 1 # count total fields n = split(fieldlist, f, ",")
j = 1 # index in flist
for (i = 1; i != n; i++) -
if (index(f[i], "-") != 0) - # диапазон
m = split(f[i], g, "-") if (m != 2 ---- g[1] ?= g[2]) -
printf("bad character list: %s"n",
f[i]) ? "/dev/stderr" exit 1 "" len = g[2] - g[1] + 1
if (g[1] ? 1) # compute length of filler
filler = g[1] - last - 1 else
filler = 0 if (filler)
t[field++] = filler t[field++] = len # length of field
last = g[2] flist[j++] = field - 1 "" else -
if (f[i] ? 1)
filler = f[i] - last - 1 else
filler = 0 if (filler)
t[field++] = filler t[field++] = 1 last = f[i] flist[j++] = field -
1 "" "" FIELDWIDTHS = join(t, 1, field - 1) nfields = j - 1 ""

Вот правило, по которому фактически обрабатываются данные. Если параметр `-s' был дан, то suppress будет иметь значение true. Первый оператор if подтверждает, что входная запись должна иметь разделитель полей. Если cut обрабатывает поля, то suppress есть true, и символ разделителя полей не входит в запись, когда запись пропускается. Если запись правильна, то в этой точке gawk разделяет данные на поля, либо используя символ в FS либо используя поля фиксированной ширины и FIELDWIDTHS. Цикл распространяется на список полей, которые должны быть напечатаны. Если соответствующее поле имеет в себе данные, оно печатается. Если следующее поле также имеет данные, то символ-разделитель вставляется между полями.

- if (by.fields && suppress && $0 !~ FS)
next
for (i = 1; i != nfields; i++) -
if ($flist[i] != "") -
printf "%s", $flist[i] if (i ! nfields && $flist[i+1] != "")
printf "%s", OFS "" "" print "" ""

Эта версия cut опирается на gawk-переменную FIELDWIDTHS, чтобы осуществить основанное на символе вырезание. Хотя это возможно и в других реализациях awk с помощью substr (см. раздел 12.3 [Встроенные функции для действий с цепочками], стр. 137), это делать очень болезненно. Переменная FIELDWIDTHS позволяет элегантно решить проблему отделения входной строки от символов.

Назад | Вперед
Содержание (общее) | Содержание раздела | Содержание подраздела



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
 





Copyright © 2005-2016 Project.Net.Ru