Более элегантный подход к добавлению текста в файл, только если String не существует?

Безусловно, самый простой способ — использовать инструмент, который уже есть во FreeBSD для этого-newsyslog.

Создайте файл /etc/newsyslog.confили отредактируйте существующий. Вы указываете имя файла (вы можете использовать подстановочные знаки, хотя вам может понадобиться несколько строк для разных каталогов ), сколько обратных копий вы хотите сохранить (очень большое число в вашем случае ), когда прокручивать файл (есть флаг, позволяющий вам сделать это самостоятельно ), какую систему сжатия вы хотите использовать и т. д.

Используйте newsyslog -FvC path-to-your-log-fileдля запуска в первый раз.

Кстати, вы можете просто поместить соответствующие строки в
/usr/local/etc/newsyslog.conf.d, в файле с любым именем. Это немного облегчает запоминание после обновлений.

2
17.07.2019, 14:51
4 ответа

Если у вас есть GNU sed, это довольно просто:

sed -zi '/NoDisplay=true/!s/$/\nNoDisplay=true/' file

Опция -zобрабатывает сразу всю строку в пространстве шаблонов (не рекомендуется для больших файлов ). Если параметр(!)не найден, добавьте в конце встроенный символ новой строки. Примечание :-i, -zи \nв замещающей строке не являются стандартными, поэтому они не переносимы.

6
27.01.2020, 21:49

Это немного короче.

grep -q 'NoDisplay=true' '/usr/share/applications/yelp.desktop' || echo "NoDisplay=true" >> /usr/share/applications/yelp.desktop

Существует также инструмент, предназначенный для этого Augeas(augtool). Я не использовал его с файлом .desktop. Так что не могу помочь с тем, как его использовать.

5
27.01.2020, 21:49

Используя sed, на основании этого ответа:

sed -i "/^NoDisplay=true\$/h;\${x;/^\$/{s//NoDisplay=true/;H};x}" '/usr/share/applications/yelp.desktop'

Сломан без выхода $с:

# Store the line in the hold space if found
/^NoDisplay=true$/h

# At the end of the file
${
    # Switch to the hold space
    x
    # If it's empty
    /^$/{
        # Replace the line
        s//NoDisplay=true/
        # Store it in the hold space
        H
    }
    # Switch to the hold space
    x
}

Это можно сделать в awk, но поскольку до GNU 4.1.0 не было редактирования на месте , вы, по сути, делаете то же самое, что и grep+ echo.

2
27.01.2020, 21:49

Я думаю, что единственные, возможно, неэлегантные вещи в вашем подходе — это использование bash -c, которое не требуется, и избыточность литеральных строк, которые вы использовали для шаблона и имени файла, которые фактически делают ваш один -лайнер длинный, и который вы могли бы вместо этого поместить в переменные (, возможно, короткие -с именем )для использования, как в:

p='NoDisplay=true' f='/usr/share/applications/yelp.desktop'; grep -q "${p}" "${f}" || echo "${p}" >>"${f}"

Вы можете сделать это немного более компактным, поэкспериментировав с перенаправлениями, просто чтобы не указывать имя файла дважды и, следовательно, не использовать одну переменную, как в:

p='NoDisplay=true'; (grep -q "${p}" || echo "${p}" >&0) <>/usr/share/applications/yelp.desktop

Но будет ли это на самом деле элегантно, вероятно, вопрос предпочтения.

В любом случае, шаблон все равно нужно указать дважды, хотя и через переменные. Я не могу представить, как можно этого избежать.

Еще один вариант с sed, который позволит сэкономить всего несколько нажатий клавиш, может быть:

p='NoDisplay=true'; sed -n "/${p}/q;\$a${p}" <>/usr/share/applications/yelp.desktop >&0

Требуется GNUsed(обычно присутствует в Linux )из-за команды a, за которой сразу следует добавляемый текст (переменная шаблона в нашем случае ).

То же самое для POSIX sedбудет:

p='NoDisplay=true'; sed -n "/${p}/q;\$a\\
${p}
" <>/usr/share/applications/yelp.desktop >&0
1
27.01.2020, 21:49

Теги

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