2017-01-06 2 views
2

Я хочу объединить строки в файле, как показано ниже.Unix как конкатенировать строки по шаблону

Входной

01EPH087362 SHHFHDH 3673 
63737 
Dhdhj 
01EPH636363 DHHDH 
3637737 
Hshshhd 
01EPH7373838 HDJJDJ 

Выход

01EPH087362 SHHFHDH 3673 63737 Dhdhj 
01EPH636363 DHHDH 3637737Hshshhd 
01EPH7373838 HDJJDJ 

Я хочу, чтобы выход, как указано выше; в основном каждая строка должна начинаться с 01EPH.

У меня есть awk и sed, но вам не повезло. Пожалуйста, помогите, если вы знаете.

+0

В вашем представлении использование пространств для разделения соединенных линий является непоследовательным. –

ответ

1

Входной

$ cat f 
01EPH087362 SHHFHDH 3673 
63737 
Dhdhj 
01EPH636363 DHHDH 
3637737 
Hshshhd 
01EPH7373838 HDJJDJ 

Выход

$ awk '(s=/^01EPH/) && NR>1{print ""}{printf("%s%s",(s?"":" "),$0)}END{print ""}' f 
01EPH087362 SHHFHDH 3673 63737 Dhdhj 
01EPH636363 DHHDH 3637737 Hshshhd 
01EPH7373838 HDJJDJ 
+1

Это действительно креативно – dawg

+0

@dawg: Спасибо, дорогая –

1
awk '/^01EPH/ { if (record != "") print record; record = ""; pad = "" } 
    { record = record pad $0; pad = " " } 
    END { if (record != "") print record }' 

Если линия начинается 01EPH, печать сохраненной информации, если есть, и опустошить сохраненную информацию и отступы.

В каждой строке добавьте пэд и новую строку к сохраненной информации; установите пэд на пробел.

В конце напечатайте сохраненную запись, если в ней что-либо есть.

Это даже чудесно сохраняет двойное пространство между DHHDH и 3637737Hshshhd, потому что на линии заканчивается DHHDH.

Выход:

01EPH087362 SHHFHDH 3673 63737 Dhdhj 
01EPH636363 DHHDH 3637737 Hshshhd 
01EPH7373838 HDJJDJ 
-1

Один лайнер:

tr '\n' ' ' < file.txt | sed s/01EPH/\\n01EPH/g 

tr '\n' ' ' < file.txt - делает один струнный

sed s/01EPH/\\n01EPH/g - префикс 01EPH по новой строки

+1

Это вставляет новые строки перед каждым «01EPH», даже если оно произошло в середине другой строки в середине строки. 'Tr' также удаляет все новые строки, которые превращают его вывод в нетекстовый файл (на POSIX), поэтому любое заданное sed или любой другой инструмент с этим является неопределенным поведением и, таким образом, YMMV с этим. В лучшем случае он также добавляет ведущую новую строку и конечный пустой символ и не предоставляет завершающую новую строку, поэтому YMMV с тем, что вы можете сделать с этим выходом. Короче говоря, не делайте этого. –

+1

Вы правы. Во всяком случае, я сохраню этот ответ, на всякий случай. Надеюсь, люди читают комментарии :) – streetturtle

2
$ awk '/^01EPH/{if (NR>1) print buf; buf=$0; next} {buf = buf OFS $0} END{print buf}' file 
01EPH087362 SHHFHDH 3673 63737 Dhdhj 
01EPH636363 DHHDH 3637737 Hshshhd 
01EPH7373838 HDJJDJ 
1

Мое мнение:

awk ' 
    /^01EPH/ {printf "%s%s", nl, $0; nl = "\n"; next} 
    {printf " %s", $0} 
    END {print ""} 
' file 
1

другой awk

$ $ awk 'NR>1 && /^01EPH/ {print ""} 
          {printf "%s", $0 OFS} 
     END    {print ""}' file 

01EPH087362 SHHFHDH 3673 63737 Dhdhj 
01EPH636363 DHHDH 3637737 Hshshhd 
01EPH7373838 HDJJDJ 

добавить новую строку, когда шаблон совпадает (за исключением первой строки) и в конце, в противном случае добавить строки ...

1

Если у вас есть файл только с \ п линейных окончаний, вы могли бы использовать

sed 's/^01EPH/\r&/;$s/$/\r/' inputfile | tr -d "\n" | tr "\r" "\n" 

Первая часть sed вставок a \r перед каждым 01EPH. Вторая часть добавляет один в конец, так что последняя строка также закончится линией перевода строки. Теперь удалите исходные переводы строк и замените отмеченные на них линией.
Он проходит через файл 3 раза, поэтому любое решение awk будет лучше для большого файла, но я просто хотел показать tr с sed.

0

Вот чистый Bash (плюс printf), чтобы сделать это только для хихикает:

while IFS= read -r line || [[ -n $line ]]; do 
    if [[ "$line" =~ ^01EPH ]]; then 
     printf "%s%s" "$pad" "$line" 
     pad=$'\n' 
    else 
     printf " %s" "$line" 
    fi 
done <file 

Вот Perl чавкать решение:

perl -0777 -ne 'while (/(^01EPH.*?)(?=^01EPH|\z)/gms) {($st=$1)=~s/\n/ /g; print "$st\n" }' file 

В обоих случаях awk, вероятно, лучше .. .

1

@suyog: Не могли бы вы также попробовать следующее и сообщить мне, если это вам поможет.

awk '{printf("%s%s",($0 ~ /^01E/ && NR>1)?ORS:NR>1?FS:"",$0)} END{print ""}' Input_file 

Результат будет следующим.

01EPH087362 SHHFHDH 3673 63737 Dhdhj                                   
01EPH636363 DHHDH 3637737 Hshshhd                                    
01EPH7373838 HDJJDJ