Обработка текста оболочки AWK / KSH / Подсчет по группам [закрыто]

Finalmente he llegado a la solución aceptada. Gracias a @B Layer por su cooperación (p. mencionando que el comando wsolo escribe líneas completas en un archivo ). He votado tu respuesta.

:let i=1
:1000 | exec 'normal! )hvggd' | exec 'if i<10 | let num="0". i | else | let num=i | endif' | call writefile(split(@@, "\n", 1), '/tmp/test'. num. '.txt') | let i=i+1

Después de eso, repite el comando presionando @:si el último fragmento tiene menos de 1000 líneas, obtendrás un error. Simplemente guarde el resto manualmente.

Después de 5 ejecuciones tuve lo esperado:

$ wc -l /tmp/test*.txt
  1001 /tmp/test01.txt
  1000 /tmp/test02.txt
  1001 /tmp/test03.txt
  1006 /tmp/test04.txt
  1001 /tmp/test05.txt

Para aquellos que quieran usarlo, explicaré brevemente los pasos clave:

:1000

Mover a la línea 1000 (Los fragmentos deben tener al menos 1000 líneas de largo)

exec 'normal! )hvggd'

Mover al comienzo de la siguiente oración y un carácter hacia atrás para que el primer carácter de la siguiente oración no se elimine después. Para que funcione correctamente en oraciones que se distribuyen en varias líneas, se debe configurar whichwrap=h,l, que no es el valor predeterminado que yo sepa. Seleccione todo, desde la posición actual del cursor hasta el comienzo y elimínelo. El contenido eliminado se guardará en el registro.

call writefile(split(@@, "\n", 1), '/tmp/test'. num. '.txt')

Escribir el contenido del registro (el fragmento )en un archivo

Partí del supuesto de que no habrá más de 99 fragmentos. Si necesita más, ajuste la parte relacionada con el relleno según sea necesario.

-3
25.08.2017, 20:26
3 ответа

Возможно:

< file sort | awk '{print $0 "\t" ++n[$1]}'
1
28.01.2020, 05:19

Однократная сортировка предоставленных выборочных данных возвращает выходные данные в том же порядке, в котором они были запрошены. Предположим, что строка заголовка не включена в сортировку.

sort datafile

Следующим шагом является подсчет количества раз, когда мы видели одинаковые идентификаторы для заполнения столбца 5. Мы также заменяем заголовок, чтобы включить новый столбец 5.

Мы хотим пропустить исходную строку заголовка из вашего синтаксического анализа awk.

awk 'BEGIN {print "ID\tNAME\tCOMPANY\tYEAR\tCOUNT"} NR>1 {id_count[$1]++; print $0 "\t" id_count[$1]}' datafile

Если первая строка файла данных является заголовком, awk игнорирует эту строку, (требуя, чтобы номер строки/записи был больше 1 ).

Просто соедините команды, соединив первую команду со второй. В следующем примере мы предполагаем, что строка заголовка не включена в вывод sort.

sort datafile | awk 'BEGIN {print "ID\tNAME\tCOMPANY\tYEAR\tCOUNT"}  {id_count[$1]++; print $0 "\t" id_count[$1]}'

Команда сортировки по умолчанию включает все поля, так что в итоге вы получите сортировку по столбцам, в которых сначала будут идентификаторы, затем имена, затем компании и годы. Команда awk печатает новый заголовок (, более или менее повторяющий исходный ), и добавляет столбец COUNT.

Остальные строки данных анализируются путем проверки поля 1 (ID )с использованием ассоциативного массива. Каждая строка печатается как есть с табуляцией, и к ней добавляется количество просмотров столбца 1.

Окончательный оператор печати может сначала сбить с толку, но символ пробела в awk является конкатенатором. $0, вкладка и значение переменной будут сжаты вместе в выводе. Другой способ написать это мог быть;

printf "%s\t%d\n",$0,id_count[$1]
1
28.01.2020, 05:19

Ответ Стефана Шазела хорош, но не учитывает заголовок данных. Также предполагается, что конкретный IDвсегда соответствует одним и тем же NAMEи COMPANY.

Если это не так, то вам придется сделать это немного по-другому:

sort -k1,1 -k4,4 file.in | awk '{ print $0, ++n[$1] }'

Чтобы получить правильный заголовок:

sed '1d' file.in |
sort -k1,1 -k4,4 |
awk -vOFS="\t" \
   'BEGIN { print "ID", "NAME", "COMPANY", "YEAR", "Count" }
          { print $0, ++n[$1] }'

Это удаляет заголовок из ввода, сортирует файл по IDи YEAR, а затем повторно -вставляет заголовок с новым столбцом Count. Затем он увеличивает счетчик для каждого IDи выводит текущее значение этого счетчика в последнем столбце для каждой строки ввода :

.
ID      NAME    COMPANY YEAR    Count
111     LUIS    TCS     2015    1
111     LUIS    TCS     2015    2
111     LUIS    TCS     2016    3
222     URSO    XYZ     2014    1
222     URSO    XYZ     2015    2
333     OMAR    ABC     2014    1
333     OMAR    ABC     2015    2
444     SANJIB  MABE    2011    1
444     SANJIB  MABE    2012    2

Если вы хотите, чтобы awkвыбрал исходный заголовок из файла и просто добавил заголовок Countбез необходимости вводить его снова, вы также можете сделать это:

sed -e '1w /tmp/header.txt' -e '1d' file.in |
sort -k1,1 -k4,4 |
awk -vOFS="\t" \
   'NR == 1 { getline h <"/tmp/header.txt"; print h, "Count" }
            { print $0, ++n[$1] }'

rm -f /tmp/header.txt

Это заставляет sedзаписать заголовок в файл /tmp/header.txt. Когда первая запись читается awk, этот файл считывается в переменную hи выводится вместе с новым столбцом Count. Остальная часть скрипта awkработает так же, как и раньше, и выдает тот же результат.

Файл /tmp/header.txtгарантированно существует для чтения скриптом awk, поскольку он не будет прочитан до тех пор, пока не будет получена первая входная запись. В этот момент sortиспользует все входные данные из sed, что означает, что заголовочный файл должен быть записан. Чтение его в блоке BEGINпотенциально не сработает.

0
28.01.2020, 05:19

Теги

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