Объединить значения последовательных строк, если они имеют одинаковые значения в другом столбце (AWK)

Мне нужно совместить первое значение ($1) последовательных строк, если их четвертое значение ($4) одинаково (I-PER).

Мне удалось отфильтровать значения I нужно просто использовать awk:

awk ' ($4 == "I-PER") {printf $1; printf "\n" }

Я также нашел, как объединить строки с повторяющимися значениями столбца, но не последовательными.

Пример (вход):

Comandante comandante NP00000 I-PER de de SPS00 I-PER la el DA0FS0 I-PER Guardia guardia NP00000 I-PER Civil civil NP00000 I-PER Pamplona pamplona NP00000 I-LOC Poblador poblador NP00000 I-PER

Пример (вывод):

Comandante de la Guardia Civil Poblador
2
задан 13 April 2018 в 10:54

6 ответов

Другое решение awk, чтобы избежать повторной печати \n ewlines, если условие не встречалось ни в одной строке:

awk '($4=="I-PER"){ printf SEP$1; SEP=" "; C=1; next } 
      C==1{ SEP=""; print ""; C=0} END{print ""}' infile

пример ввода:

Comandante  comandante  NP00000 I-PER
de  de  SPS00   I-PER
la  el  DA0FS0  I-PER
Guardia guardia NP00000 I-PER
Civil   civil   NP00000 I-PER
no I-PER in fourth column
anotherline no I-PER in fourth column
Pamplona    pamplona    NP00000 I-LOC
Poblador    poblador    NP00000 I-PER

выход:

Comandante de la Guardia Civil
Poblador
2
ответ дан 22 May 2018 в 11:27

Другое решение awk, чтобы избежать повторной печати \n ewlines, если условие не встречалось ни в одной строке:

awk '($4=="I-PER"){ printf SEP$1; SEP=" "; C=1; next } C==1{ SEP=""; print ""; C=0} END{print ""}' infile

пример ввода:

Comandante comandante NP00000 I-PER de de SPS00 I-PER la el DA0FS0 I-PER Guardia guardia NP00000 I-PER Civil civil NP00000 I-PER no I-PER in fourth column anotherline no I-PER in fourth column Pamplona pamplona NP00000 I-LOC Poblador poblador NP00000 I-PER

выход:

Comandante de la Guardia Civil Poblador
2
ответ дан 17 July 2018 в 16:56

Другое решение awk, чтобы избежать повторной печати \n ewlines, если условие не встречалось ни в одной строке:

awk '($4=="I-PER"){ printf SEP$1; SEP=" "; C=1; next } C==1{ SEP=""; print ""; C=0} END{print ""}' infile

пример ввода:

Comandante comandante NP00000 I-PER de de SPS00 I-PER la el DA0FS0 I-PER Guardia guardia NP00000 I-PER Civil civil NP00000 I-PER no I-PER in fourth column anotherline no I-PER in fourth column Pamplona pamplona NP00000 I-LOC Poblador poblador NP00000 I-PER

выход:

Comandante de la Guardia Civil Poblador
2
ответ дан 23 July 2018 в 17:47

Быстрое и несколько грязное решение с тернарным оператором (condition?true:false), оно выполняет тест, который вы предоставили, и печатает либо $1, либо пробел или новую строку:

awk '{printf $4=="I-PER"?$1" ":"\n"}'

Выход:

$ <test awk '{printf $4=="I-PER"?$1" ":"\n"}'
Comandante de la Guardia Civil 
Poblador

Вот довольно бедный альтернативный подход с массивом - по крайней мере, это не создает пустые строки, как показано выше, для нескольких последовательных строк I-PER:

awk '{
  if ($4=="I-PER") {a[i++]=$1}
  else if (length(a)>0) {
    for (i in a) {printf a[i]" ";delete a[i]}
    print ""
    }
  }
 END {
  if (length(a)>0) {
    for (i in a) printf a[i]" ";print ""}
  }'

Выход:

$ <test awk '{if($4=="I-PER"){a[i++]=$1}else if(length(a)>0){for(i in a){printf a[i]" ";delete a[i]};print ""}}END{if(length(a)>0){for(i in a)printf a[i]" ";print ""}}'
Comandante de la Guardia Civil 
Poblador
0
ответ дан 22 May 2018 в 11:27

Быстрое и несколько грязное решение с тернарным оператором (condition?true:false), оно выполняет тест, который вы предоставили, и печатает либо $1, либо пробел или новую строку:

awk '{printf $4=="I-PER"?$1" ":"\n"}'

Выход:

$ <test awk '{printf $4=="I-PER"?$1" ":"\n"}' Comandante de la Guardia Civil Poblador

Вот довольно бедный альтернативный подход с массивом - по крайней мере, это не создает пустые строки, как показано выше, для нескольких последовательных строк I-PER:

awk '{ if ($4=="I-PER") {a[i++]=$1} else if (length(a)>0) { for (i in a) {printf a[i]" ";delete a[i]} print "" } } END { if (length(a)>0) { for (i in a) printf a[i]" ";print ""} }'

Выход:

$ <test awk '{if($4=="I-PER"){a[i++]=$1}else if(length(a)>0){for(i in a){printf a[i]" ";delete a[i]};print ""}}END{if(length(a)>0){for(i in a)printf a[i]" ";print ""}}' Comandante de la Guardia Civil Poblador
0
ответ дан 17 July 2018 в 16:56

Быстрое и несколько грязное решение с тернарным оператором (condition?true:false), оно выполняет тест, который вы предоставили, и печатает либо $1, либо пробел или новую строку:

awk '{printf $4=="I-PER"?$1" ":"\n"}'

Выход:

$ <test awk '{printf $4=="I-PER"?$1" ":"\n"}' Comandante de la Guardia Civil Poblador

Вот довольно бедный альтернативный подход с массивом - по крайней мере, это не создает пустые строки, как показано выше, для нескольких последовательных строк I-PER:

awk '{ if ($4=="I-PER") {a[i++]=$1} else if (length(a)>0) { for (i in a) {printf a[i]" ";delete a[i]} print "" } } END { if (length(a)>0) { for (i in a) printf a[i]" ";print ""} }'

Выход:

$ <test awk '{if($4=="I-PER"){a[i++]=$1}else if(length(a)>0){for(i in a){printf a[i]" ";delete a[i]};print ""}}END{if(length(a)>0){for(i in a)printf a[i]" ";print ""}}' Comandante de la Guardia Civil Poblador
0
ответ дан 23 July 2018 в 17:47

Другие вопросы по тегам:

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