У меня есть текстовый файл со следующим форматом. Первая строка - "КЛЮЧ", а вторая строка - "VALUE".
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
Как объединить две строки в одну?
Ответ 1
AWK:
awk 'NR%2{printf "%s ",$0;next;}1' yourFile
Заметьте, что в конце вывода есть пустая строка.
СЭД:
sed 'N;s/\n/ /' yourFile
Ответ 2
paste
подходит для этой работы:
paste -d " " - - < filename
Ответ 3
Альтернатива sed, awk, grep:
xargs -n2 -d'\n'
Это лучше всего, когда вы хотите присоединиться к N строкам, и вам нужен только объемный вывод.
Мой первоначальный ответ был xargs -n2
, который отделяется от слов, а не от строк. -d
может использоваться для разделения ввода на любой отдельный символ.
Ответ 4
Есть больше способов убить собаку, чем повешение. [1]
awk '{key=$0; getline; print key ", " $0;}'
Поместите любой разделитель в кавычки.
Литература:
- Первоначально "Множество способов скинуть кошку", вернулось к более старому, потенциально происходящему выражению, которое также не имеет ничего общего с домашними животными.
Ответ 5
Хотя кажется, что предыдущие решения будут работать, если в документе возникнет одна аномалия, вывод будет разложен. Ниже немного безопаснее.
sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
Ответ 6
Вот еще один способ с 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
(Запись Separator), который является новой линией.
Если вы хотите добавить ,
в качестве разделителя, используйте следующее:
awk '{ ORS = (NR%2 ? "," : RS) } 1' file
Ответ 7
Вот мое решение в bash:
while read line1; do read line2; echo "$line1, $line2"; done < data.txt
Ответ 8
"ex" - это редактор сценариев, который находится в том же семействе, что и sed, awk, grep и т.д. Я думаю, это может быть то, что вы ищете. Многие современные vi-клоны/преемники vi также имеют режим vi.
ex -c "%g/KEY/j" -c "wq" data.txt
Это говорит для каждой строки, если она соответствует "KEY", выполните команду j в следующей строке. После завершения этой команды (против всех строк) выполните обход w и q uit.
Ответ 9
Вы можете использовать awk, чтобы объединить все две пары строк:
awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
END {if (length(line)) print line;}' flle
Ответ 10
Если параметр Perl является опцией, вы можете попробовать:
perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
Ответ 11
Вы также можете использовать следующую команду vi:
:%g/.*/j
Ответ 12
Небольшое отклонение от glenn jackman answer с помощью paste
: если значение для параметра -d
delimiter содержит более одного символа, paste
циклически проходит символы один за другим и в сочетании с параметрами -s
продолжают делать это при обработке одного и того же входного файла.
Это означает, что мы можем использовать все, что хотим, в качестве разделителя плюс 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$3
KEY 0:1772 string$1
KEY 4192:1349 string$1
KEY 7329:2407 string$2
KEY 0:1774 string$1
То, что это не может сделать, это использовать разделитель, состоящий из нескольких символов.
В качестве бонуса, если 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
Ответ 13
Другие решения, использующие vim (только для справки).
Решение 1:
Откройте файл в vim vim filename
, затем выполните команду :% normal Jj
Эту команду очень легко понять:
- %: для всех строк,
- нормальный: выполнить нормальную команду
- Jj: выполнить команду Join, а затем перейти к строке ниже
После этого сохраните файл и выйдите с помощью :wq
Решение 2:
Выполните команду в оболочке, vim -c ":% normal Jj" filename
, затем сохраните файл и выйдите с помощью :wq
.
Ответ 14
nawk '$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s\n", $0}' filename
Это означает, что
$0 ~ /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
Ответ 15
В случае, когда мне нужно было объединить две строки (для облегчения обработки), но разрешить данные за конкретным, я нашел это полезным
data.txt
string1=x
string2=y
string3
string4
cat data.txt | nawk '$0 ~ /string1=/ { printf "%s ", $0; getline; printf "%s\n", $0; getline } { print }' > converted_data.txt
вывод тогда выглядит так:
converted_data.txt
string1=x string2=y
string3
string4
Ответ 16
Самый простой способ:
- Удалите четные строки и запишите их в некоторый временный файл 1.
- Удалить нечетные строки и записать их в некоторый временный файл 2.
- Объедините два файла в одном, используя команду вставки с -d (означает удаление пространства)
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
Ответ 17
perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt
-0
копирует весь файл, а не читает его по очереди.
pE
обертывает код циклом и выводит результат, см. подробности в http://perldoc.perl.org/perlrun.html;
^KEY
сопоставить "KEY" в начале строки, после чего следует нежелательное соответствие чего-либо (.*?
) перед последовательностью
- одно или несколько пробелов
\s+
любого типа, включая разрывы строк;
- одна или несколько цифр
(\d+)
, которые мы фиксируем, а затем снова вставляем как $1
;
за которым следует конец строки $
.
\K
удобно исключает все из его левой части из подстановки, поэтому { $1}
заменяет только 1-2 последовательности, см. http://perldoc.perl.org/perlre.html.
Ответ 18
Более общее решение (допускает объединение нескольких последующих строк) в виде оболочки script. Это добавляет линию между каждым, потому что мне нужна видимость, но это легко исправить. В этом примере заканчивается строка "ключ": и никаких других строк не было.
#!/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
Ответ 19
Попробуйте следующую строку:
while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file
Вставить разделитель между
"$line1 $line2";
например. если разделитель |
, то:
"$line1|$line2";
Ответ 20
Вы можете использовать xargs
следующим образом:
xargs -a file