Разделение длинных строк на bash с нумерацией - PullRequest
2 голосов
/ 08 июля 2020

Я пытаюсь написать сценарий, который разбивает очень длинный текст (одна строка) на несколько строк. Требование - каждая строка должна иметь префиксы с нумерацией. Я пробовал использовать sed, но у меня проблема с нумерацией совпадений. Мой код:

 sed -e "s/.\{4\}/part = &\\
 /g"

Вход:

AAAAAAAAABBBBBBBAAAAAAABBBBBBB

Выход:

part = AAAA
part = AAAA
part = ABBB
part = BBBB
part = AAAA
part = AAAB
part = BBBB
BB

Ожидается:

part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB

Дополнительная проблема - последняя часть, которая не имеет маркировки. Можно ли это сделать с помощью sed? Или, может быть, любые другие инструменты оболочки?

Ответы [ 6 ]

4 голосов
/ 08 июля 2020

«Жесткая» часть этого, фактическое разделение ввода на строки, - это работа, для которой существует fold:

$ echo 'AAAAAAAAABBBBBBBAAAAAAABBBBBBB' |
    fold -w 4 | awk '{print "part" NR " = " $0}'
part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB

Использование fold облегчит вашу жизнь, если / когда ваши требования изменяются, например, старайтесь разбивать только на пробелы.

4 голосов
/ 08 июля 2020

С GNU awk:

awk '{for(i=1; i<=NF; i++){print "part" i,"=",$i}}' FPAT='.{1,4}' file

Вывод:

part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB

From man awk:

FPAT: регулярное выражение, описывающее содержимое полей в записи. Если установлено, gawk анализирует ввод в поля, где поля соответствуют регулярному выражению, вместо использования значения FS в качестве разделителя полей.

1 голос
/ 09 июля 2020

Другой GNU awk с использованием встроенной переменной RT:

$ echo AAAAAAAAABBBBBBBAAAAAAABBBBBBB | 
awk -v RS=".{1,4}" '{printf "%spart%d = %s",(++i>1?ORS:""),i,RT}'

Пример вывода:

part1 = AAAA
part2 = AAAA
...
part8 = BB
1 голос
/ 08 июля 2020

С инструментами GNU:

echo "$str" | grep -oE '.{,4}' | nl -s ' = ' | sed -E 's/^ +/part/'
part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB
1 голос
/ 08 июля 2020

Вот более простое gnu awk решение:

s='AAAAAAAAABBBBBBBAAAAAAABBBBBBB'
awk -v RS='[^\n]{1,4}' 'RT{print "part" NR, "=", RT}' <<< "$s"
part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB 
0 голосов
/ 09 июля 2020

В вашем коде = в строке замены команды s - это просто буквальный символ =, а не номер строки. Эта проблема может быть решена в чистом sed с помощью 3 sed команд в конвейере, например:

line='AAAAAAAAABBBBBBBAAAAAAABBBBBBB'

echo "$line"                  |
sed 's/.\{4\}/&\n/g; s/\n$//' |
sed =                         |
sed 'N; s/\(.*\)\n\(.*\)/part\1 = \2/'

который выводит

part1 = AAAA
part2 = AAAA
part3 = ABBB
part4 = BBBB
part5 = AAAA
part6 = AAAB
part7 = BBBB
part8 = BB
...