Как объединить каждые две строки в одну из командной строки?
у меня есть текстовый файл следующего формата. Первая строка - это "ключ", а вторая строка - "значение".
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:
выполните команду в shell,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.
более общее решение (позволяет объединить несколько последующих строк) в качестве сценария оболочки. Это добавляет линию между ними, потому что мне нужна была видимость, но это легко исправить. В этом примере строка " key " заканчивается на : и никаких других строк не было.
#!/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
попробуйте следующую строку:
while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file
поставить разделитель между
"$line1 $line2";
например, если разделитель |
, тогда:
"$line1|$line2";