Как объединить каждые две строки в одну из командной строки?
у меня есть текстовый файл со следующим форматом. Первая строка-это "ключ", а вторая строка - "значение".
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
циклы через символы один за другим, и в сочетании с-s
options продолжает делать это при обработке одного и того же входного файла.это означает, что мы можем использовать все, что мы хотим иметь в качестве разделителя плюс 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