AWK - печатать последний столбец вместе с пустым значением

Для этого можно использовать массивы bash, например:

arr="(first second third)"
echo ${arr[1]}

-121--38932-

Вот два взаимоисключающих цикла sed :

sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' <<""
YEAR MONTH DAY RES
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1972 1     1   549
1972 1     2   746
...
1972 12    31  999
1972 1     1   933
1972 1     2   837
...
1972 12    31  343

YEAR MONTH DAY RES
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1972 1     1   549
1972 1     2   746
...
1972 12    31  999

В основном sed имеет два состояния - p rint и eat . В первом состоянии - p rint state - sed автоматически p печатает каждую входную строку, затем проверяет ее по /12 * 31/ образцы. Если текущее пространство образца равно ! не совпадает с d , и sed тянет в следующей строке ввода и снова запускает сценарий сверху - по команде p rint без попытки выполнить что-либо, что следует за командой d elete вообще.

Если входная строка соответствует /12 * 31/, однако sed попадает во вторую половину сценария - цикл eat . Сначала определяется метка ветви : с именем n ; затем он перезаписывает текущий образец пространство на n ext, а затем сравнивает текущий образец пространство с // последним согласованным образцам. Поскольку строка, которая соответствовала ей ранее, только что была перезаписана с помощью n ext, первая итерация этой eat петли не совпадает, и каждый раз, когда она делает ! не sed b возвращается к метке : n , чтобы получить n ext входную строку и еще раз сравнить ее с // последней соответствующего образца.

При окончательном совпадении - некоторые 365 n ext строки позже - sed автоматически печатает -n ot по завершении сценария, тянет в следующей строке ввода и снова начинает с вершины команды p rint в первом состоянии. Таким образом, каждое состояние цикла будет падать до следующего на тот же ключ и делать как можно меньше в то же время, чтобы найти следующий ключ.

Обратите внимание, что весь сценарий завершается без вызова одной процедуры редактирования и что ему требуется только компиляция одного regexp. Этот результат очень прост - он понимает только и [^ 123] . Более того, по крайней мере половина сравнений, скорее всего, будет выполнена без каких-либо компиляций, потому что единственным адресом, на который ссылается цикл eat , является пустой адрес //. Поэтому sed может полностью завершить этот цикл одним вызовом regexec () для каждой входной линии. sed может также выполнять аналогичные действия для цикла p .


время


Мне было интересно, как различные ответы здесь могут работать, и поэтому я придумал свой собственный стол:

dash <<""
    d=0 D=31 IFS=: set 1970 1
    while   case  "$*:${d#$D}" in (*[!:]) ;;
            ($(($1^($1%4)|(d=0))):1:)
                     D=29 set $1 2;;
            (*:1:)   D=28 set $1 2;;
            (*[3580]:)
                     D=30 set $1 $(($2+1));;
            (*:)     D=31 set $(($1+!(t<730||(t=0)))) $(($2%12+1))
            esac
    do      printf  '%-6d%-4d%-4d%d\n' "$@" $((d+=1)) $((t+=1))
    done|   head    -n1000054 >/tmp/dates

dash <<<''  6.62s user 6.95s system 166% cpu 8.156 total

Это помещает миллион + строк в /tmp/даты и удваивает выход для каждого из 1970 - 3338 лет. Файл выглядит так:

tail -n1465 

3336  12  27  728
3336  12  28  729
3336  12  29  730
3336  12  30  731
3336  12  31  732
3337  1   1   1
3337  1   2   2
3337  1   3   3
3337  1   4   4
3337  1   5   5

3338  12  22  721
3338  12  23  722
3338  12  24  723
3338  12  25  724
3338  12  26  725
3338  12  27  726
3338  12  28  727
3338  12  29  728
3338  12  30  729
3338  12  31  730

... некоторые из них в любом случае.

И затем я попробовал различные команды на нем:

for  cmd in "sort -uVk1,3" \
            "sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn'" \
            "awk '"'{u=$1 $2 $3 $4;if (!a[u]++) print;}'\'
do   eval   "time ($cmd|wc -l)" 

500027
( sort -uVk1,3 | wc -l; ) \
1.85s user 0.11s system 280% cpu 0.698 total

500027
( sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' | wc -l; ) \
0.64s user 0.09s system 110% cpu 0.659 total

500027
( awk '{u=$1 $2 $3 $4;if (!a[u]++) print;}' | wc -l; ) \
1.46s user 0.15s system 104% cpu 1.536 total

Команды сортировки и sed были выполнены менее чем за половину времени awk - и эти результаты были типичными. Я управлял ими несколько раз. Похоже, все команды также записывают правильное количество строк - и поэтому, вероятно, все они работают.

sort и sed были довольно хорошо шея и шея - с sed обычно волосы впереди - для времени завершения для каждого прогона, но sort делает больше фактической работы для достижения своих результатов, чем любая из двух других команд. Он выполняет параллельные задания для выполнения своей задачи и получает значительные преимущества от многоядерных процессоров. awk и sed оба привязываются к назначенному одноядерному ядру в течение всего времени его обработки.

Результаты здесь из стандартного, актуального GNU sed , но я попробовал другой. На самом деле, я попробовал все три команды с другими двоичными файлами, но только команда sed фактически работала с моими инструментами heirloom. Остальные, как я полагаю из-за нестандартного синтаксиса, просто уходят с ошибкой, прежде чем оторваться от земли.

Хорошо использовать стандартный синтаксис, когда это возможно - вы можете свободно использовать более простые, отточенные и эффективные реализации во многих случаях, которые путь:

PATH=/usr/heirloom/bin/posix2001:$PATH; time ...

500027
( sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' | wc -l; ) \
0.31s user 0.12s system 136% cpu 0.318 total

-121--96733-

Почему grep ? Для поиска используется команда grep . Вам, кажется, нужно либо вырезать , либо неловко , но читаемый builtin также кажется подходящим.

Сравните их:

users | cut -d' ' -f1
users | sed 's/\s.*//'
users | awk '$0=$1'

Если вы хотите сохранить их в переменной, используйте bash:

read myVar blah < <(users)

или:

read myVar blah <<< $(users). 

Выше ответ на основе @ manatwork comments .

2
01.06.2018, 12:34
4 ответа

Para generar solo la última columna de filas que tienen el número máximo de columnas, podría hacer algo como:

who | awk '
  NF > max  {max = NF; output = ""}
  NF == max {output = output $NF ORS}
  END       {printf "%s", output}'

Para generar una fila por cada fila de entrada, pero vacío para las filas que no tienen el número máximo de columnas:

who | awk '
  NF > max {max = NF}
  {n[NR] = NF}
  NF == max {last[NR] = $NF}
  END {for (i = 1; i <= NR; i++) print n[i] == max ? last[i] : ""}'
5
27.01.2020, 21:50

Si solo desea obtener la última columna si esta columna está disponible, use el hecho de que las líneas que no desea tienen solo cuatro columnas:

who | awk 'NF > 4 { print $NF }'

o, para obtener datos similares,

w -hi | awk '{ print $3 }'
0
27.01.2020, 21:50

Compruebe si el quinto campo coincide con \(.*\)e imprímalo si coincide.

who | awk '$5 ~ /\(.*\)/{print $5}'

Si solo está interesado en las direcciones ip, cambie la expresión regular:

who |  awk '$5 ~ /\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)/{print $5}'
1
27.01.2020, 21:50

Si desea el último campo solo de las líneas que tienen la mayor cantidad de campos, deberá leer los datos dos veces :una vez para encontrar la mayor cantidad de campos y otra vez para imprimir los campos. Leer solo una vez no es suficiente :cualquier línea puede tener más campos que las anteriores, y no hay forma de saberlo.

Conawk(tenga en cuenta que el nombre del archivo se da dos veces):

awk -vfields=0 'FNR==NR {if (NF > fields) fields=NF; next} 
     NF >= fields { print $NF } NF < fields {print ""}' file file

Si filecontiene

foo bar
one two three four
1 2 3
a b c d

esto imprime el cuarto campo, o vacío para las líneas que no lo tienen:


four

d

Eso, por supuesto, no funciona con una tubería, tendrás que usar un archivo temporal.

Una solución alternativa podría almacenar en caché los -campos impresos -hasta que aparezca una línea con más campos, como en la respuesta de Stéphane .

3
27.01.2020, 21:50

Теги

Похожие вопросы