Как объединить пары последовательных строк в большой файл (1 миллион строк) с помощью vim, sed или другого аналогичного инструмента? - PullRequest
13 голосов
/ 17 декабря 2011

Мне нужно переместить содержимое каждой второй строки вверх на строку выше, чтобы данные в строке 2 находились рядом с данными в строке line1, либо через запятую, либо через пробел.Вывод:

line1 line2
line3 line4

Я делаю это в vim с простой записью, но vim, кажется, вылетает, когда я говорю это делать 100 000 раз ... Я думаю, что sed будетхорошая альтернатива, но не знаете, как делать то, что я хочу, или, может быть, есть лучший вариант?

Каждая строка содержит только 1 числовое значение, у меня просто миллион строк ...

Ответы [ 8 ]

16 голосов
/ 17 декабря 2011

Если я правильно понимаю, у вас есть:

line1 
line2
line3
line4
...

и вы хотите:

line1<SEP>line2
line3<SEP>line4

, тогда вы можете легко сделать это с помощью (g)awk, например:

awk 'NR % 2 == 1 { o=$0 ; next } { print o "<sep>" $0 }' INPUTFILE

Смотрите его в действии здесь .

Обновление : если число строк нечетное, в приведенной выше строке будет пропущена последняя строка (как Мартин Стеттнеруказал) так что это не будет:

awk 'NR % 2 == 1 { o=$0 ; next } { print o "<sep>" $0 } END { if ( NR % 2 == 1 ) { print o } }' INPUTFILE

HTH

8 голосов
/ 05 мая 2012

Команда вставки может сделать это. Его опция "-s" будет соединять последовательные строки; а опция "-d" указывает список символов для использования в качестве разделителей, повторяя их циклически. Присоединитесь сначала с пробелом, затем с новой строкой и повторите:

seq 10 | paste -sd" \n" -
8 голосов
/ 17 декабря 2011

попробуйте это:

sed -rn 'N;s/\n/ /;p' yourFile

тест с последовательностью:

kent$  seq 10
1
2
3
4
5
6
7
8
9
10

kent$  seq 10|sed -rn 'N;s/\n/ /;p'
1 2
3 4
5 6
7 8
9 10

awk тоже работает:

awk 'NR%2{printf $0" ";next;}1' yourFile

тест

kent$  seq 10|awk 'NR%2{printf $0" ";next;}1'
1 2
3 4
5 6
7 8
9 10
7 голосов
/ 19 декабря 2011

Ну, ваш пример в Vim.

:g/^/+t.|-j

Но как насчет последней строки?

Или ты это имел ввиду?

:g/^/j

Вас также может заинтересовать этот скрипт Vim, который облегчает работу с большими файлами.

http://www.vim.org/scripts/script.php?script_id=1506

7 голосов
/ 17 декабря 2011

Это может сработать для вас:

sed 'N;s/\n/ /' file

или

cat file | paste -d' ' - - 

или другой парой способов, описанных выше:

paste -d\  - - <file

paste -sd' \n' file
2 голосов
/ 19 декабря 2011
$ seq 10 | sed '2~2G' | awk -v RS='' '{$1=$1; print}'
1 2
3 4
5 6
7 8
9 10

$ paste -d' ' <(sed -n 'p;n' num.txt) <(sed -n 'n;p' num.txt)
1 2
3 4
5 6
7 8
9 10

$ echo -e 'g/^/,+1j\n%p' | ex num.txt
1 2
3 4
5 6
7 8
9 10

$ seq 10 | awk 'NR%2{printf("%s ", $0); next}1'
1 2
3 4
5 6
7 8
9 10

$ seq 10 | sed 'N;s/\n/ /'
1 2
3 4
5 6
7 8
9 10

примечание: $ seq 10 >num.txt

1 голос
/ 10 апреля 2019

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

cat file | xargs

будет повторяться

line1 line2 line3 line4

Но вы можете ограничить число прочитанных строк с помощью опции -n

cat file | xargs -n 2

будет иметь желаемый эффект объединения каждых двух строк:

line1 line2
line3 line4

Если строки могут содержать пробелы, необходимо явно указать входной разделитель (новая строка)

cat file | xargs -n 2 -d '\n'

И, наконец, не используйте cat таким образом, скажем вместо этого

xargs -n 2 -d '\n' <file

или даже

xargs -n 2 -d '\n' -a file
1 голос
/ 29 сентября 2017
seq 10 | awk 'ORS=NR%2?FS:RS'

Это решение использует "троичный оператор" для установки ORS

ORS= ....... output register separator (will receive =)
NR%2 ....... test if it has division remainder of Number of Register by 2
?FS:RS ..... FS = "space" RS = "\n" (newline)
...