конвейерная команда после того, как grep не работает

Sysfs вовсе не является подмножеством procfs. Они служат разным целям, см. ответы на В чем разница между procfs и sysfs?.

3
18.12.2017, 10:43
3 ответа

используйте - строчная буферизация включите grep

tail -3f logfile.log | grep --line-buffered "action.*add" | sed -u -e "s/^/'/" -e "s/$/'/" | xargs -L 1 -P 5 bash testscript.sh

от man grep:

- строчная буферизация Использовать строчную буферизацию при выводе. Это может привести к снижению производительности.


или вы можете использовать stdbuf подробнее

stdbuf позволяет изменять операции буферизации трех стандартных потоков ввода-вывода, связанных с программой. Сводка:

используйте этот синтаксис:

... | stdbuf -oL grep ... | ...

ваш пример:

tail -3f logfile.log | stdbuf -oL grep "action.*add" | sed -u -e "s/^/'/" -e "s/$/'/" | xargs -L 1 -P 5 bash testscript.sh
8
20.08.2021, 12:04

Проблема, с которой вы, вероятно, столкнулись, - это «конвейерная буферизация»; вывод различных компонентов конвейера (в вашем случае grep ) больше не буферизуется по строкам, а буферизуется по блокам, а размер буфера может составлять 4 КБ или около того. Следующий компонент не видит данные сразу. Он увидит это, когда накопится достаточно данных ...

Решение немного болезненное. К счастью, пакет expect поставляется с командой unbuffer , которая может помочь. man unbuffer для получения более подробной информации о том, как это использовать.

Он работает, заставляя компоненты конвейера думать, что они общаются с терминалом, и поэтому остаются в буфере строки.

1
20.08.2021, 12:04

Как отмечали другие, буферизация строк grep является очевидной причиной вашей проблемы.

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

Для начала, похоже, что вы используете sed для добавления апострофов в начало и конец каждой выходной строки, чтобы вы могли передать их в xargs . В этом нет необходимости даже удаленно - xargs имеет параметр -d , который вы можете использовать, чтобы указать ему использовать символы новой строки в качестве разделителя: например, xargs -d '\ n' -r (параметр -r - убедиться, что xargs ничего не делает, если нет строк ввода)

Во-вторых , вы используете регулярные выражения для анализа данных json. Это ненадежно, чрезвычайно сложно или даже невозможно разобраться со сложными / вложенными структурами, хрупко и легко сломается по тем же причинам, по которым использование регулярных выражений для синтаксического анализа XML или HTML ненадежно, чрезвычайно сложно и хрупкий. Не анализируйте XML или HTML с помощью регулярных выражений . Это не работает . То же самое относится к json .

Вместо этого вы должны использовать что-то вроде jq или jsonpipe для извлечения полей из данных json.Например:

jq -c 'select(.twNotif.action == "add")' file.txt | 
  xargs -d'\n' -r -L 1 -P 5 ./testscript.sh

Если вы хотите передать значение поля действия по конвейеру xargs (без двойных кавычек), вы можете сделать это следующим образом:

jq 'select(.twNotif.action == "add") | .twNotif.action' file.txt | 
  sed -e 's/"//g' | 
  xargs -d'\n' -r -L 1 -P 5 ./testscript.sh

Использование jsonpipe и awk , вероятно, будет проще для такой работы:

jsonpipe < file.txt | 
  awk '$1 == "/twNotif/action" {gsub(/"/,""); print $2}' |
  xargs -d'\n' -r -L 1 -P 5 ./testscript.sh

(обратите внимание на перенаправление там, в отличие от jq , jsonpipe ] работает только со стандартным вводом).

Кстати, jsonpipe преобразует данные json в строчно-ориентированный формат, подходящий для использования с такими инструментами, как sed , grep , awk и т. Д. Например:

$ jsonpipe < file.txt
/   {}
/twNotif    {}
/twNotif/originator "api"
/twNotif/chain  "test"
/twNotif/txId   "08640-0050568a5514"
/twNotif/version    "1.0"
/twNotif/msgType    "api"
/twNotif/twData {}
/twNotif/twData/api {}
/twNotif/twData/api/hostId  "007bdcc5"
/twNotif/twData/api/user    "test"
/twNotif/twData/api/cmdTxt  "100599"
/twNotif/action "add"
/twNotif/store  "test"
/twNotif/msgTime    1467280648.971042

С ним проще работать, чем с jq , особенно если вам не нужен вывод в формате json.

Это также полезно для перечисления структуры и полей / элементов в json-файле в форме, которую можно легко использовать с jq . например:

$ jsonpipe <file.txt | awk '{gsub(/\//,"."); print $1}'
.
.twNotif
.twNotif.originator
.twNotif.chain
.twNotif.txId
.twNotif.version
.twNotif.msgType
.twNotif.twData
.twNotif.twData.api
.twNotif.twData.api.hostId
.twNotif.twData.api.user
.twNotif.twData.api.cmdTxt
.twNotif.action
.twNotif.store
.twNotif.msgTime
3
20.08.2021, 12:04

Теги

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