При условии соответствия 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" только потому, что именно это я использовал для тестирования. Эд Мортон отметил, что мое решение не использует непереносимых функций , однако.