Finalmente he llegado a la solución aceptada. Gracias a @B Layer por su cooperación (p. mencionando que el comando w
solo 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.
Однократная сортировка предоставленных выборочных данных возвращает выходные данные в том же порядке, в котором они были запрошены. Предположим, что строка заголовка не включена в сортировку.
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]
Ответ Стефана Шазела хорош, но не учитывает заголовок данных. Также предполагается, что конкретный 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
потенциально не сработает.