Используйте sed для вставки текста перед двумя пустыми строками

Для относительно небольших файлов, (где длина в байтах меньше, чем getconf ARG_MAX), а размеры входных данных более или менее известны, (скажем, ни одно имя фрукта не превышает 18 букв ), printfможет быть полезно, вот пример bash:

 printf '%-20s %5s %5s\n' $(<file.txt)

Выход:

apple                    1   100
orange                  20    19
pineapple             1000    87
avocado                  4    30

Обратите внимание, как числа выровнены по правому краю .

0
04.05.2021, 13:13
3 ответа

Использование awkвместоsed:

newdata='This is the new data'

newdata=$newdata awk -F '\n' -v OFS='\n' -v RS= -v ORS='\n\n' \
    '$1 == "# SECTION ONE" { $(NF+1) = ENVIRON["newdata"] }; 1' file

или

newdata='This is the new data'

newdata=$newdata awk '
    BEGIN { FS = OFS = "\n"; RS = ""; ORS = "\n\n" }
    $1 == "# SECTION ONE" { $(NF+1) = ENVIRON["newdata"] }; 1' file

Это помещает awkв "режим чтения абзаца" с использованием пустого значения для RS, разделителя входных записей. Это означает, что awkбудет читать абзац за раз. «Абзац» — это любой набор строк, разделенных хотя бы одной пустой строкой.

Затем мы устанавливаем разделитель полей ввода, FS, на символ новой строки с -F '\n', так что каждая строка в абзаце становится отдельным полем.

Мы также устанавливаем выходные -соответствующие переменные ORSи OFSтаким образом, чтобы записи (абзацев )выводились с завершающей пустой строкой, и чтобы поля (строк внутри абзаца )выводятся с завершающим символом новой строки.

Фактический код определяет, когда первая строка абзаца точно соответствует строке # SECTION ONE. В этом случае в конец текущей записи добавляется новое поле с новыми данными. Новые данные берутся из переменной окружения newdata.

Все абзацы, измененные или нет, затем выводятся безоговорочно.

Обратите внимание, что если фактический файл конфигурации (, который мы никогда не увидим в вопросе ), написан в XML, YAML, JSON или каком-либо другом формате структурированного документа, тогда этот ответ является недействительным ,поскольку эти форматы документов требуют надлежащего формата -инструментов для чтения и записи (, поскольку они не ориентированы на строки -и поскольку данные требуют кодирования/декодирования ).

2
28.07.2021, 11:35

Используя GNU sed, мы можем сделать следующее:

sed -e '/# SECTION ONE/,/^$/s/^$/__NEW-DATA__\n/' file

Оператор диапазона в awk может использоваться для получения желаемого результата

awk '
  /# SECTION ONE/,!NF{
    if (!NF) print "__NEW-DATA__"
  }1
' file

Этот метод использует конструкции POSIXly sed

sed -e '
  /# SECTION ONE/!b
  :a
    n;/^$/!ba
  G;s/^/__NEW-DATA__/
' file

В этом методе мы помещаем новые данные перед именем секции, при условии, что она не первая. Предполагая, что размер файла составляет не менее 3 строк.

sed -e '
  1,2N
  $q;N
  s/^\n\n# SECTION TWO/__NEW-DATA__\n&/;t
  P;D
' file
1
28.07.2021, 11:35

Прочитав еще раз комментарий Кусаландры и вопрос, я понимаю его так же, как он или она.

В GNU -sed есть переключатель для включения стиля POSIX, поэтому я надеюсь, что на этот раз эта команда не зависит от варианта sed -.

Исходный файл:

cat FILE
# SECTION ONE
data...
data...
data...

# SECTION TWO
data...
data...

Команда:

sed --posix "s/^[ \t]*$/...new data.../; /# SECTION TWO/i\\ " FILE

# SECTION ONE
data...
data...
data...
...new data...
 
# SECTION TWO
data...
data...

Обратите внимание, что вставка оставляет пустое место в файле, которое может быть удалено с помощью последующей команды sed или может быть обработано usind s/^[ \t]*$как регулярное выражение, которое соответствует пустым строкам и таким пустым местам. пробелов и/или вкладок.

Альтернатива:

sed --posix "s/^$/...new data.../; /# SECTION TWO/i\ " -e "s/^ $//" FILE 

Вторая форма использует вторую команду sed (-e -, возможно, третью, после использования двух команд, разделенных ;в первых кавычках )для удаления пробела, если это не так. t терпимо и, следовательно, догматично в поиске пустых строк.

0
28.07.2021, 11:35

Теги

Похожие вопросы