объединить первую строку в текстовом блоке с каждой следующей строкой в ​​блоке - PullRequest
0 голосов
/ 17 января 2019

Я пытался выяснить, как объединить первую строку в текстовом блоке с каждой другой строкой блока, используя awk или sed. Каждый блок состоит из 2 или более строк, например:

AA  
1  

BB  
2  
3  
4  

CC  
5  
6  
7  
8  

Как я могу объединить это с выводом ниже:

AA 1  
BB 2  
BB 3  
BB 4  
CC 5  
CC 6  
CC 7  
CC 8  

Любая помощь очень ценится.

Ответы [ 4 ]

0 голосов
/ 17 января 2019

GNU sed:

$ sed -rn '/^\s*$/{s/.*//;h;be};/./{x;/./!be;x;G;s/(.*)\n(.*)/\2 \1/p};:e' file
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8

Обрабатывает только пробелы / символы табуляции только как пустые строки.
Если таких строк нет, их можно сократить:

sed -rn '/^$/{h;be};/./{x;/./!be;x;G;s/(.*)\n(.*)/\2 \1/p};:e'
0 голосов
/ 17 января 2019

Еще один awk!

$ cat pckh.txt
AA
1

BB
2
3
4

CC
5
6
7
8

$ awk ' NF && !/[A-Z]/ { print prev,$0 } /[A-Z]/ {  prev=$0 }  ' pckh.txt
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8

$
0 голосов
/ 17 января 2019
$ awk -v RS= '{for (i=2;i<=NF;i++) print $1, $i}' file
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8
0 голосов
/ 17 января 2019

При условии соответствия POSIX awk и оболочки * это будет работать ...

awk '/^[[:space:]]*$/ {a=""} {if (a=="") {a=$0} else print a,$0}'

Объяснение того, как это работает (ОБНОВЛЕНИЕ):

Есть два действия. Первая реагирует на пустую строку (за исключением необязательных пробелов), поскольку ей предшествует этот шаблон: /^[[:space:]]*$/. Косые черты, конечно, просто разграничивают рисунок. Символ каретки (^) соответствует началу строки, а знак доллара ($) соответствует концу. Это вызывает совпадение всей строки (в противном случае этот шаблон будет соответствовать любой строке вообще, потому что каждая возможная строка ввода содержит ноль или более пробельных символов). [[:space:]]* соответствует нулю или более (*) символов из предопределенного класса символов пробельных символов. Действие для этого шаблона сбрасывает переменную (бессмысленно именуемую a) в пустую строку. Это используется для определения начала следующего текстового блока.

Второе действие не имеет шаблона и поэтому выполняется один раз для каждой строки ввода. Он проверяет, был ли уже установлен префикс (опять же, переменная a), и:

  • Если это не так, он устанавливает префикс для содержимого текущей строки ($0). (Обратите внимание, что это также бесполезно выполняется в пустой строке.)
  • Если это так, он печатает префикс, за которым следует содержимое текущей строки. (awk автоматически вставляет пробел из-за использования запятой.)

По иронии судьбы, я обнаружил ошибку при написании этого обновления: строка, содержащая только пробел, будет принята в качестве префикса. Это потому, что в этом случае проверка if (a=="") не проходит. Есть несколько способов решить эту проблему. Я не знаю достаточно о awk себя, чтобы рекомендовать конкретный подход, но, похоже, это делает:

awk '/^[[:space:]]*$/ {s=1;a=""} {if (s==0 && a=="") a=$0; else print a,$0; s=0}'

*) Я изначально (и лениво) написал "GNU awk and bash" только потому, что именно это я использовал для тестирования. Эд Мортон отметил, что мое решение не использует непереносимых функций , однако.

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