Поставте текст перед кожним новим рядком, який програма друкує для stdout


9

Тому я хочу зробити якийсь журнал і для цього хочу поставити дату перед вихідним сценарієм bash. Проблема полягає в тому, що є кілька ліній виводу. Я можу лише поставити дату перед усім результатом. Але тоді я маю рядок без дати у журналах. Звичайно, я можу припустити, що дата з рядка вище однакова, але я сподівався, що є рішення. Спасибі заздалегідь!

Це мій сценарій, який викликає інший сценарій:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

Це вихід:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

І ось що я хотів би мати:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended

Я не думаю, що ви могли просто змінити другий сценарій?
jmetz

Ні, на жаль, ні. Тому я прийшов сюди.
tzippy

Відповіді:


9

Відповідно до подібного питання щодо Stack Overflow , є 2 чудових варіанти.

awk ( відповідь )

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

примітка ( відповідь )

annotate - це невеликий скрипт bash, який можна отримати безпосередньо за посиланням, поданим тут, або, на базі систем Debian, через пакет devscripts(у формі annotate-output).


3

Я думаю, що ви можете використовувати awk для цього:

./script.sh | awk '{ print strftime()" : "$0; }'

(див. http://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html для форматування дати, що повертається стропом ())


2
awk: calling undefined function strftime- це специфічно для gawk?
Даніель Бек

Тепер, коли ви згадуєте про це, так, здається, це: /
Флінт

2

Можна використовувати awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awkприймає потік введення та змінює його вихід. Цей сценарій говорить "надрукувати d з подальшим вихідним результатом", а потім заповнюється dдатою.


1
Чи не це оцінює також dateвираз лише один раз, так що всі такі рядки друкуються однаково?
Даніель Бек

@DanielBeck Так - я припускав, що збирає дату кожен раз, але щойно закінчив мій тест досить швидко
Пол

1

Це надрукує поточну дату та час перед кожним рядком виводу ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

Як це працює

  • set -fвимикає розширення bash (або echo *не надрукує фактичну зірочку).

  • while read -r LINE; do ... doneзберігає один рядок виводу у змінній $LINEта виконує ..., поки всі рядки не будуть оброблені.

  • echo $ (дата "+% F% T"): "$ LINE" друкує рядок з поточним часом та датою.

  • set +f знову вмикає розширення bash, тож воно не заважатиме решті вашого скрипту bash.


Він оцінюється лише один раз, тому кожен sedвставляє ту саму дату, безпосередньо перед запуском другого сценарію. Мабуть, не те, чого хоче користувач ...
Даніель Бек

Я не думаю, що ця спроба теж не спрацює. AFAIK, спочатку повністю оцінюється вся підсфера, потім проходить цикл. Тож зараз часи починаються після страти.
Даніель Бек

Ваш приклад не працює, оскільки ви затримуєте лише вихід, а не виконання ls. Просто спробуйте свій сценарій із наступним script.sh: #!/bin/bash(новий рядок)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Даніель Бек

Використовуйте readз whileциклом замість петлі.
чепнер

@chepner: Гарна ідея.
Денніс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.