Создавать новый столбец при каждом появлении определенного значения строки, используя awk [дубликат]

Мне удалось найти временное исправление, установив xterm и открыв текстовые файлы в xterm с помощью nano. Однако я не понимаю, почему он не использует URXVT и nano для того же самого

.
1
20.05.2018, 16:48
3 ответа

dividir y pegar

Use csplitpara dividir un archivo en múltiples archivos en un patrón. Luego use pastepara unir los nuevos archivos.

awk 'NF' column.txt | csplit --suppress-matched -s -z -f INTERIM -n 4 - '/start newset/' '{*}' ; paste INTERIM* | expand -t 6,13 ; rm -f INTERIM*

El mismo código, reformateado para mayor claridad:

awk 'NF' column.txt | \
csplit --suppress-matched -s -z -f INTERIM -n 4 - '/start newset/' '{*}' ;

paste INTERIM* | \
expand -t 6,13 ;

rm -f INTERIM*

Descripción:

  • awk 'NF' column.txt
    Eliminar líneas vacías. De lo contrario, las líneas vacías en el archivo de entrada colocarían separadores de columna adicionales en la salida.
  • dividir
    • --suppress-matched
      No incluya líneas que contengan el patrón de división en la salida.
    • -s
      No mostrar información resumida sobre los archivos de salida.
    • -z
      No produzca archivos de salida vacíos (, es decir, cuando dos líneas adyacentes del archivo de entrada contienen el patrón de división ).
    • -f INTERIM
      Los nombres de archivo de los archivos divididos comienzan con esta cadena.
    • -n 4
      Los nombres de archivo de los archivos divididos terminan con un número que contiene tantos dígitos.
    • -
      Tome la entrada de STDIN, ya que primero estamos ejecutando el archivo de entrada a través de awk.
    • '/start newset/'
      Dividir el archivo de entrada en la primera línea que contiene esta expresión regular.
    • '{*}'
      Siga dividiendo el archivo de entrada en cada línea adicional que contenga esa expresión regular.
  • paste INTERIM*
    Únase a los archivos provisionales.
  • expand -t 6,13
    Ajuste el espacio entre columnas entre los archivos unidos (, por ejemplo, comience el segundo archivo en la columna 6 y el tercer archivo en la columna 13 ).
  • rm -f INTERIM*
    Eliminar los archivos provisionales.

Ejemplo de archivo de entradacolumn.txt:

1 1.1
2 4.0
3 3.2
start newset
1 2.2
2 6.1
3 10.3
4 2.1
start newset
1 18.2
2 4.3

Ejemplo de salida:

1 1.1 1 2.2  1 18.2
2 4.0 2 6.1  2 4.3
3 3.2 3 10.3 
      4 2.1  

Es un poco más complicado si las líneas del archivo de entrada y la salida final están sangradas.

Ejemplo de archivo de entradacolumn.txt:

  1 1.1
  2 4.0
  3 3.2
  start newset
  1 2.2
  2 6.1
  3 10.3
  4 2.1
  start newset
  1 18.2
  2 4.3
  • Cambie awk 'NF'a awk 'NF { sub(/^ +/,"",$0) ; print $0 }'para eliminar la sangría antes de continuar con el procesamiento.
  • Cambie expand -t 6,13a awk '{ print " " $0 }' | expand -t 8,15para sangrar la salida.

Ejemplo de salida:

  1 1.1 1 2.2  1 18.2
  2 4.0 2 6.1  2 4.3
  3 3.2 3 10.3 
        4 2.1  
2
27.01.2020, 23:16
$ awk '$1+0>=1{a[$1]=a[$1]" "$0}END{for (i in a)print a[i]}' file.txt 
 1 1.1 1 2.2 1 18.2
 2 4.0 2 6.1 2 4.3
 3 3.2 3 10.3
 4 2.1

Приведенная выше команда awk создает массив с именем a и сохраняет/добавляет значения на основе первого столбца. как только вы полностью прочитаете файл, просто напечатайте значения массива.

step 1 : a[1] = "1 1.1"
step 2 : a[2] = "2 4.0"
step 3 : a[3] = "3 3.2"
step 4 : ignore the line # 4. because the first column is not numeric
step 5 : a[1] = "1 1.1 1 2.2"
step 6 : a[2] = "2 4.0 2 6.1".
....
...
once the file is fully procssed by awk, then just print the array values a[1],a[2],a[3]...a[n]
0
27.01.2020, 23:16

Маршрут через временные файлы:

$ awk 'BEGIN { n = 1 } /^start newset/ { n++; next } { name = sprintf("tmp-%04d", n); print >name }' file

Это не приведет к выводу в терминал, но создаст файлы с именем tmp-n, где n— это заполненное нулем -четырехзначное -целое число, большее или равное 1. Будет один файл для каждый набор данных.

Затем мы можем склеить эти временные файлы вместе:

$ paste tmp-*
1 1.1   1 2.2   1 18.2
2 4.0   2 6.1   2 4.3
3 3.2   3 10.3
        4 2.1

или с пробелами в качестве разделителей вместо табуляции:

$ paste -d ' ' tmp-*
1 1.1 1 2.2 1 18.2
2 4.0 2 6.1 2 4.3
3 3.2 3 10.3
 4 2.1

Если в данных имеется большое количество наборов, с этим:

возникают две проблемы.
  1. У вас могут закончиться файловые дескрипторы в awk. От этого можно защититься, изменив второй кодовый блок awkс

    .
    { name = sprintf("tmp-%04d", n); print >name }
    

    -

    { name = sprintf("tmp-%06d", n); print >>name; close(name) }
    

    (обратите внимание на изменение строки форматирования, чтобы можно было использовать большие числа)

  2. Могут возникнуть проблемы с выполнением команды paste, так как шаблон tmp-*расширяется до слишком большого количества файлов. Дайте мне знать, если это проблема, и я разберусь с ней, тогда (будет цикл оболочки, который создает результат путем добавления столбцов из tmp-*файлов ).

1
27.01.2020, 23:16

Теги

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