Как объединить каждые две строки в одну из командной строки? - PullRequest
125 голосов
/ 07 марта 2012

У меня есть текстовый файл в следующем формате.Первая строка - это «КЛЮЧ», а вторая - «ЗНАЧЕНИЕ».

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 ]

3 голосов
/ 26 августа 2014

Вы также можете использовать следующую команду vi:

:%g/.*/j
3 голосов
/ 15 ноября 2017

Небольшое отклонение ответа Гленна Джекмана с использованием paste: если значение параметра -d разделитель содержит более одного символа, 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
1 голос
/ 08 января 2016

Другие решения, использующие vim (просто для справки).

Решение 1 :

Откройте файл в vim vim filename, затем выполните команду :% normal Jj

Эту команду довольно просто понять:

  • %: для всех строк
  • normal: выполнить обычную команду
  • Jj: выполнить команду Join, затем перейдите к строке ниже

После этого сохраните файл и выйдите с помощью :wq

Решение 2 :

Выполнитевведите в командной строке vim -c ":% normal Jj" filename, затем сохраните файл и выйдите с помощью :wq.

1 голос
/ 01 ноября 2013
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
1 голос
/ 22 октября 2014

В случае, когда мне нужно было объединить две строки (для упрощения обработки), но разрешить данные за пределами конкретной, я нашел это полезным

data.txt * 1005Выходные данные *

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

выглядят следующим образом:

convert_data.txt

string1=x string2=y
string3
string4
0 голосов
/ 11 апреля 2014

Самый простой способ здесь:

  1. Удалить четные строки и записать их в некоторый временный файл 1.
  2. Удалить нечетные строки и записать его в некоторый временный файл 2.
  3. Объедините два файла в один, используя команду вставки с -d (означает удаление пробела)

sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
0 голосов
/ 17 мая 2016

Попробуйте следующую строку:

while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file

Поместите разделитель между

"$line1 $line2";

Например, если разделитель |, тогда:

"$line1|$line2";
0 голосов
/ 04 мая 2016

Вы можете использовать xargs так:

xargs -a file
0 голосов
/ 26 сентября 2014

Более общее решение (допускает объединение нескольких последующих строк) в виде сценария оболочки.Это добавляет грань между каждым, потому что мне нужна была видимость, но это легко исправить.В этом примере строка «ключа» оканчивалась на: остальные строки не были.

#!/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
0 голосов
/ 28 августа 2014
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» в начале строки, за которым следует не жадное совпадение чего-либо (.*?) перед последовательностью

  1. одного или нескольких пробелов \s+ любого вида, включая разрывы строк;
  2. одна или несколько цифр (\d+), которые мы фиксируем, а затем снова вставляем как $1;

с последующим концом строки $.

\K удобно исключает все, что находится слева от замены, поэтому { $1} заменяет только последовательность 1-2, см. http://perldoc.perl.org/perlre.html.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...