정규식이 일치할 때마다 명령을 실행하고 EOF 없이 stdin에서 읽습니다.

정규식이 일치할 때마다 명령을 실행하고 EOF 없이 stdin에서 읽습니다.

dbus-monitor의 출력에서 ​​특정 문자열이 발견될 때마다 타임스탬프(파일에 기록될)를 생성하는 BASH 스크립트를 작성하려고 합니다(매개변수는 나중에 지정됨). 내 스크립트의 주요 목적은 알림을 사용하기 때문에 Spotify에서 노래가 재생되기 시작하는 시간(밀리초 포함)과 날짜를 절약하는 것입니다.

string "Spotify"노래가 재생될 때마다 다음 명령이 출력됩니다.

dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' | grep 'string "Spotify"'

내 시도:

search='string "Spotify"'
found=$(dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' | grep 'string "Spotify"')

while [ ${search} == ${found} ]; do
    date -u +%Y%M%d-%H%M%S.%N >> timestamp.txt
done

코드 기능 장애의 원인은 dbus-monitor가 계속 실행되어 while 루프의 실행을 차단하기 때문이라고 가정합니다.

답변1

awk대신 사용하십시오 grep. 다음과 같습니다.

dbus-monitor ... | awk '/Spotify/ {
    system("date -u +%Y%m%d-%H%M%S.%N >> timestamp.txt")
  }'

( 월이 아닌 분 동안 -M %Y%m%d대신 대문자 M이 사용됩니다 . CAPS-D는 동일합니다 .)%Y%M%D%m/%d/%y

이것은 입력에 "Spotify"가 표시될 때마다 awk의 system()기능을 사용하여 하위 쉘에서 date 명령을 실행합니다 . 또는 awk에 내장된 날짜 형식과 리디렉션을 사용하세요.

dbus-monitor ... | awk '/Spotify/ {
    print strftime("%Y%m%d-%H%M%S") >> "timestamp.txt"
  }'

strftime()이 버전은 지원되지 않기 때문에 타임스탬프에 나노초를 인쇄하지 않습니다 %N.

아니면 awk 대신 perl을 사용하세요. 이렇게 하면 Perl을 사용할 수 있습니다.데스크탑::알림알림을 받기 위한 모듈 또는네트워크::DBusdbus와 직접 통신하세요.

답변2

GNU 유틸리티가 있으므로 다음을 수행할 수 있습니다.

dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' |
  sed -un 's/^.*string "Spotify".*$/now/p' |
  stdbuf -oL date -uf - +%Y%m%d-%H%M%S.%N >> timestamp.txt

dbus-monitor이미버퍼링 비활성화, 그래서 stdbuf -oL거기에는 필요가 없습니다.

-uGNU의 옵션은 sed출력 버퍼링을 비활성화하고 여기에서 검색할 수 없는 경우 입력을 한 번에 한 바이트씩 읽도록 합니다. 후자가 필요하지는 않지만, 읽자마자 한 줄을 출력하려면 전자가 필요합니다.

여기서는 sed포함된 줄이 발견될 때마다 인쇄합니다.nowstring "Spotify"

그것은 표준 입력 에서 읽고 인쇄하는 Feed.use now입니다 . 각 읽기에 대해 현재 시간을 지정된 형식으로 인쇄합니다. 출력이 청크 단위가 아닌 즉시 파일에 들어가도록 보장합니다.date-f -datedatenowstdbuf -oLtimestamp.txt

zsh/bash/ksh93을 사용하여 현재 시간을 출력하는 것 외에 임의의 명령을 실제로 실행하려면 다음을 수행할 수 있습니다.

while IFS= read -ru3 line || [ -n "$line" ]; do
  any arbitrary command
done 3< <(
  dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' |
  grep --line-buffered 'string "Spotify"'
)

답변3

이것은 작동합니다:

stdbuf -oL dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' |
while grep -q 'string "Spotify"'; do
    date -u +%Y%M%d-%H%M%S.%N >> timestamp.txt
done

@StéphaneChazelas의 댓글 이후 편집:

stdbuf -oL dbus-monitor --session interface='org.freedesktop.Notifications',member='Notify' |
grep --line-buffered 'string "Spotify"' |
while read trash; do
    stdbuf -oL date -u +%Y%M%d-%H%M%S.%N >> timestamp.txt
done

+1 다른 답변이지만 완전성을 위해 이 답변을 유지합니다.

답변4

dbus-monitor이 경우 타임스탬프(에포크 시간 + 마이크로초 단위)가 제공된 것처럼 보입니다 . 따라서 date모든 게임에 대해 이를 수행 할 필요는 없을 것입니다 . 예를 들어 arg0='Spotify'다음을 사용하여 일치하는 표현식의 범위를 좁힐 수 있습니다 .

이 출력을 확인하십시오.

dbus-monitor "
  type='method_call',
  interface='org.freedesktop.Notifications',
  member='Notify',
  arg0='Spotify'"

Spotify의 알림과 관련된 dbus 메시지만 볼 수 있기를 바랍니다. (테스트할 수 없습니다. 이것은 단지 살펴보는 것뿐입니다.버스 사양). 이것이 작동한다면 다음이 적절할 수 있습니다.

dbus-monitor --profile "type='method_call',
  interface='org.freedesktop.Notifications', member='Notify', arg0='Spotify'" |
gawk -F '\t' '
  $NF=="Notify" {
    secs = usecs = $2
    sub(/^[^.]+/,"",usecs)
    print strftime("%Y%m%d-%H%M%S",int(secs),"UTC") usecs
    fflush()
  }' > timestamp.log

--profile기본 출력보다 구문 분석하기가 더 쉬워 보이기 때문에 출력 형식 에 사용됩니다 --monitor. 타임스탬프를 추출하고 형식을 지정하려면 GNU로 파이프하세요 awk.

관련 정보