Для относительно небольших файлов, (где длина в байтах меньше, чем 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
Обратите внимание, как числа выровнены по правому краю .
Использование 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 или каком-либо другом формате структурированного документа, тогда этот ответ является недействительным ,поскольку эти форматы документов требуют надлежащего формата -инструментов для чтения и записи (, поскольку они не ориентированы на строки -и поскольку данные требуют кодирования/декодирования ).
Используя 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
Прочитав еще раз комментарий Кусаландры и вопрос, я понимаю его так же, как он или она.
В 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 терпимо и, следовательно, догматично в поиске пустых строк.