Как распечатать это с помощью AWK? - PullRequest
1 голос
/ 13 сентября 2010

У меня есть файл, который выглядит так:

1 543423 34354 
2 5654656 3423 xyz_1378,xyz_1379
3 4645656 34234354 xyz_1384,xyz_1385
4 5654 78678 xyz_1390,xyz_1391,xyz_1392
5 54654 76867 xyz_1411,xyz_1412,xyz_1413
6 54654 8678 
7 56546 67867 xyz_1711
8 678 7867 
9 76867 7876 xyz_2940
10 6786 678678 xyz_3101,xyz_3102,xyz_3103,xyz_3104,xyz_3105,xyz_3106,xyz_3107
11 67867 78678 

Обратите внимание, что оно содержит 4 поля, разделенные пробелом. последнее (четвертое) поле может быть пустым и может содержать множество значений, разделенных запятыми.

Я хотел бы напечатать все значения из последней строки, по одному на строку. как я могу это сделать (желательно с помощью awk)?

UPDATE: Мне нужно сделать это в пакетном режиме для многих файлов (получает объединенный вывод всех файлов вместе).

Это работает:

for x in *; do awk '{print $4}' $x/filename | awk --field-separator="," '{if ($0 != "") {for (i=1; i<NF+1; i++) print $i}}'; done;

и возвращает что-то вроде

xyz_1378
xyz_1221
xyz_97
xyz_132523
xyz_242

Единственное, чего мне сейчас не хватает, так это того, что я хочу, чтобы каждая строка выше начиналась с дополнительного поля - $ x (из цикла for).

Я пытался изменить print $i на print $x,$i" but x`, кажется, не распознается правильно в этой области. Есть идеи?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 13 сентября 2010

Используйте опцию -v в awk для передачи переменной в скрипт awk вместо того, чтобы полагаться на подстановку оболочки.Кроме того, вам нужен только один вызов awk

for dir in *; do 
    awk -v "dir=$dir" '
        NF==4 {
            n = split($4, a, ",")
            for (i=1; i<=n; i++) {print dir "\t" a[i]}
        }
    ' "$dir/filename"
done

или, если вы не против увидеть "dir / filename":

awk '
    NF==4 {
        n = split($4, a, ",")
        for (i=1; i<=n; i++) {print FILENAME "\t" a[i]}
    }
' */filename

Если у вас огромное количество каталогов,ваша оболочка может захлебнуться при расширении "* / filename", поэтому используйте find и xargs:

find . -type f -name filename -print0 | xargs -0 awk '...'

(требуется GNU find / xargs для параметров -print0 / -0)

0 голосов
/ 14 сентября 2010

Возможно, вы можете изменить один из операторов в вашей команде на

awk '{print FILENAME "," $4}' $x

и затем поработать над выводом этого.

FILENAME - внутренняя переменная awk для полученияимя файла, в котором он обрабатывается.

0 голосов
/ 13 сентября 2010

Используйте NF>=4 в качестве условия, чтобы увидеть, есть ли что-нибудь в поле.Тогда split($4,a,/,/) даст вам массив a со всеми значениями.Поместите это в большой массив результатов:

NF>=4 {
    n = split($4, a, /,/);
    for( i=1; i<=n; i++ ) {
        result[a[i]] = 0;
    }
}

и напечатайте его в конце:

END {
    for( val in result ) {
        print val;
    }
}

Если вы хотите отсортировать, отфильтруйте вывод, пропустив sort(1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...