Как объединить каждые две строки в одну из командной строки?
у меня есть текстовый файл со следующим форматом. Первая строка-это "ключ", а вторая строка - "значение".
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
мне нужно значение в той же строке, что и ключ. Поэтому выход должен выглядеть так...
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
было бы лучше, если бы я мог использовать какой-то разделитель, как $ или ,:
KEY 4048:1736 string , 3
как объединить две строки в одну?
20 ответов:
awk:
awk 'NR%2{printf "%s ",;next;}1' yourFileобратите внимание, что в конце вывода есть пустая строка.
sed:
sed 'N;s/\n/ /' yourFile
есть больше способов убить собаку, чем повесить. [1]
awk '{key=; getline; print key ", " ;}'поставить любой разделитель, который вам нравится внутри кавычек.
ссылки:
- первоначально "множество способов освежевать кошку", вернулось к более старому, потенциально возникающему выражению, которое также не имеет ничего общего с домашними животными.
альтернатива sed, awk, grep:
xargs -n2 -d'\n'это лучше всего, когда вы хотите соединить N строк, и вам нужно только пространство с разделителями вывода.
мой первоначальный ответ был
xargs -n2, которая разделяет на слова, а не строки.-dможет использоваться для разделения входных данных на любой один символ.
хотя кажется, что предыдущие решения будут работать, если в документе возникнет одна аномалия, вывод будет разбит на части. Ниже немного безопаснее.
sed -n '/KEY/{ N s/\n/ /p }' somefile.txt
вот еще один способ с
awk:awk 'ORS=NR%2?FS:RS' file
$ cat file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1
$ awk 'ORS=NR%2?FS:RS' file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1как сообщила Эд Мортон в комментариях лучше добавить фигурные скобки для безопасности и parens для переносимости.
awk '{ ORS = (NR%2 ? FS : RS) } 1' file
ORSобозначает выходной разделитель записей. То, что мы делаем здесь, это тестирование условия с помощьюNRкоторый хранит номер строки. Если по модулюNRявляется истинным значением (>0), то мы устанавливаем Выходной разделитель полей до значенияFS(разделитель полей), который по умолчанию является пробелом, иначе мы присваиваем значениеRS(разделитель записей), который является новой строкой.если вы хотите добавить
,в качестве разделителя, то используйте следующую конструкцию:awk '{ ORS = (NR%2 ? "," : RS) } 1' file
" ex " - это скриптовый редактор строк, который находится в том же семействе, что и sed, awk, grep и т. д. Я думаю, что это может быть то, что вы ищете. Многие современные клоны/преемники vi также имеют режим vi.
ex -c "%g/KEY/j" -c "wq" data.txtЭто говорит для каждой строки, если она соответствует "ключ" выполнить j oin следующей строки. После завершения этой команды (против всех строк), выдайте w обряд и q uit.
вы можете использовать awk, как это, чтобы объединить когда-либо 2 пары строк:
awk '{ if (NR%2 != 0) line=; else {printf("%s %s\n", line, ); line="";} } \ END {if (length(line)) print line;}' flle
небольшая вариация на ответ Гленна Джекмана используя
paste: если значение-dопция разделителя содержит более одного символа,pasteциклы через символы один за другим, и в сочетании с-soptions продолжает делать это при обработке одного и того же входного файла.это означает, что мы можем использовать все, что мы хотим иметь в качестве разделителя плюс escape последовательность
\nдля объединения двух строк одновременно.С помощью запятая:
$ paste -s -d ',\n' infile KEY 4048:1736 string,3 KEY 0:1772 string,1 KEY 4192:1349 string,1 KEY 7329:2407 string,2 KEY 0:1774 string,1и знак доллара:
$ paste -s -d '$\n' infile KEY 4048:1736 string KEY 0:1772 string KEY 4192:1349 string KEY 7329:2407 string KEY 0:1774 stringчто это не может do - это использование разделителя, состоящего из нескольких символов.
в качестве бонуса, если
pasteсовместим с POSIX, это не изменит новую строку последней строки в файле, поэтому для входного файла с нечетным числом строк, таких какKEY 4048:1736 string 3 KEY 0:1772 string
pasteне будет привязывать символ разделения на последней строке:$ paste -s -d ',\n' infile KEY 4048:1736 string,3 KEY 0:1772 string
nawk ' ~ /string$/ {printf "%s ",; getline; printf "%s\n", }' filenameэто читается как
~ /string$/ ## matches any lines that end with the word string printf ## so print the first line without newline getline ## get the next line printf "%s\n" ## print the whole line and carriage return
в случае, когда мне нужно было объединить две строки (для облегчения обработки), но разрешить данные мимо конкретного, я нашел это полезным
данные.txt
string1=x string2=y string3 string4данные кошку.тхт | nawk '$0 ~ /строка1=/ { функции printf "%ы ", $0; Гэтлину; функции printf "%З\П", $0; Гэтлину } { печать }' > converted_data.txt
вывод тогда выглядит так:
converted_data.txt
string1=x string2=y string3 string4
другие решения с использованием vim (только для справки).
Решение 1:
открыть файл в vim
vim filename, затем выполнить команду:% normal Jjэта команда quit легко понять:
- % : для всех строк,
- normal: выполнить нормальную команду
- Jj: выполнить команду Join, а затем перейти к строке ниже
после этого, сохраните файл и выйдите с
:wqрешение 2:
выполнить команду в оболочке,
vim -c ":% normal Jj" filename, затем сохраните файл и выйдите с:wq.
самый простой способ-это здесь:
- удалите четные строки и запишите их в некоторый временный файл 1.
- удалите нечетные строки и запишите их в некоторый временный файл 2.
- объединить два файла в один с помощью команды вставить С-D (означает удалить пробел)
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ }msg;' data.txt > data_merged-lines.txt
-0поглощает весь файл вместо того, чтобы читать его построчно;pEобертывает код с петлей и печатает вывод, см. подробности в http://perldoc.perl.org/perlrun.html;^KEYматч "ключ" в начале строки, а затем не жадный матч ничего (.*?) до последовательности
- один или несколько пробелов
\s+любого рода, включая разрывы строк;- - одна или более цифр
(\d+)что мы захват и позже повторно вставить как;далее следует конец строки
$.
\Kудобно исключает все на его левой стороне от замены так{ }заменяет только 1-2 последовательности, см. http://perldoc.perl.org/perlre.html.
более общее решение (позволяет объединить более одной последующей строки) в качестве сценария оболочки. Это добавляет линию между каждым, потому что мне нужна была видимость, но это легко исправить. В этом примере строка "ключ" заканчивается : и никакие другие строки не сделали.
#!/bin/bash # # join "The rest of the story" when the first line of each story # matches $PATTERN # Nice for looking for specific changes in bart output # PATTERN='*:'; LINEOUT="" while read line; do case $line in $PATTERN) echo "" echo $LINEOUT LINEOUT="$line" ;; "") LINEOUT="" echo "" ;; *) LINEOUT="$LINEOUT $line" ;; esac done