Moreutils ts로 파이프


9

직렬 포트에 들어오는 스트림이 있으며 초당 약 한 번 새 줄이 나타납니다.

wren@Raven:~$ cat /dev/ttyUSB0

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

A_Sensor1,B_22.00,C_50.00

빈 줄을 제거하고 나머지 타임 스탬프를 만들고 싶습니다.

sed는 빈 줄을 끝내고 타임 스탬프를 추가하지만 타임 스탬프를 업데이트 할 수는 없으며 호출 된 시간 만보 고합니다.

wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' -e "s/$/`date +\,%F\,%T`/"
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
^C

Moreutils의 일부인 ts를 찾았으며 업데이트 타임 스탬프를 얻기 위해 파이프에 연결할 수 있습니다.

wren@Raven:~$ cat /dev/ttyUSB0 |  ts
May 14 09:49:26 A_Sensor1,B_22.00,C_50.00
May 14 09:49:26
May 14 09:49:27 A_Sensor1,B_22.00,C_50.00
^C

그러나 ts와 sed를 올바르게 결합 할 수 없습니다.

이것은 내가 원하는 것을 해야하는 것처럼 보이며 전혀 출력을 생성하지 않습니다.

wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' | ts
^C
wren@Raven:~$

그러나 파이프 순서를 반대로하면 출력이 생성되지만 더 이상 비어 있지 않은 라인은 제거되지 않습니다. 다른 대체물은 잘 작동하므로 sed의 파이프가 작동한다는 것을 알고 있습니다.

wren@Raven:~$ cat /dev/ttyUSB0 |  ts | sed -e '/^$/d'
May 14 10:07:25 A_Sensor1,B_22.00,C_50.00
May 14 10:07:25
May 14 10:07:26 A_Sensor1,B_22.00,C_50.00
May 14 10:07:26
^C

그래서 나는 약간 당황했습니다. 아마도 sed가 원치 않는 라인을 제거하도록 할 수는 있지만 제거하기 전에 타임 스탬프를 작성하는 것은 잘못된 접근법이어야합니다.

설명과 도움을 부탁드립니다.

답변:


9

질문에 직접 대답하기 위해서는 sed버퍼링이 필요하며 이것이 유일한 문제입니다. / 플래그
로 버퍼링하지 않도록 지시하여이 문제를 해결할 수 있습니다 .-u--unbuffered

sed -u '/^$/d' /dev/ttyUSB0 | ts

테스트 하네스를 사용하지만 증거를 위해 실행해야합니다.

$ (echo -e 'banana\n\n'; sleep 2; echo 'cheese') | sed -u '/^$/d' | ts
May 14 11:26:05 banana
May 14 11:26:07 cheese

다른 스트림 편집기와 비슷한 상황에 처할 수 있습니다. 그들은 모두 약간을 버퍼링하고 싶어합니다. 그러나 모두 해결 방법이 있습니다. 테스트 한 명령은 다음과 같습니다.

... | mawk -W interactive '/./' | ts
... | gawk '/./ { print $0; fflush(); }' | ts
... | grep --line-buffered '.' | ts
... | perl -n -e 'print if /./' | ts

또 다른 아이디어는 그냥 gawk처리하도록하는 것입니다. 비어 있지 않은 줄을 필터링 하고 날짜 인쇄 를 수행 할 수 있습니다 (SO의 Kieron 덕분에 ).

awk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' /dev/ttyUSB0

행이 들어간 후에 바로 플러시됩니다. 다른 작업 gawk을 수행하려는 경우 여기에 특히 도움이됩니다 ... 네 번째 출력 열 (pre- )이 정규식과 일치 하는지 확인하려는 경우 (예 :)를 수행 할 수 있습니다 . Awk (및 그 변형)은 스트림 처리에 매우 유연합니다.ts$4~/\d{4}/

다른 테스트 장치 :

$ gawk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' <(
      echo -e 'banana\n\n';
      sleep 2;
      echo 'cheese'
  )
2014-05-14 11:13:59 banana
2014-05-14 11:14:01 cheese

1
일에 대한 sed -u. 블록 버퍼링 vs. 라인 버퍼링 문제입니다.
jfs

@Oli sed -u는 ts로 파이프 할 때 완벽하게 작동하므로 버퍼링에 대해 읽어 보겠습니다. 더 이상 당황하지 않습니다. 많은 감사합니다.
당황한

awk는 이와 같은 것들에 특히 적합합니다. awk 코드는 일반적으로 sed보다 훨씬 밀도가 높고 읽기 쉽습니다. 디버깅하는 동안 부분 결과를 보려는만큼 많은 print 문을 넣을 수 있습니다. 별도의 파일을 사용하지 않기 위해 전체 awk 프로그램을 here 문서에 넣을 수 있으며 here 문서 종결 자 문자열 주위에 따옴표를 넣으면 bash는 일반적으로 해석하려고 시도하는 모든 임베디드 토큰을 무시합니다.
Joe

0

bash는 이것을 while read루프 에서 처리 할 수 ​​있습니다

(echo -e 'banana\n\n'; sleep 2; echo 'cheese') | 
while IFS= read -r line; do 
    [[ $line ]] && echo "$(date "+%F %T") line"
done
2014-05-14 06:34:06 banana
2014-05-14 06:34:08 cheese

까다로운 매개 변수 확장으로 공백 만있는 행을 제거 할 수 있습니다. 선행 공백을 모두 제거하고 행이 비어 있는지 확인하십시오.

shopt -s extglob

(echo -e '  banana\n\t\n'; sleep 2; echo 'cheese') |
while IFS= read -r line; do
    [[ "${line/#+([[:blank:]])/}" ]] && echo "$(date "+%F %T") $line"
done

나는 그와 같은 다양한 접근법을 시도했지만 아무도 효과가 없었습니다. 코드가 작동하지 않습니다. 에코 고양이를 사용하여 보낼 수는 / dev / ttyUSB0를 While 루프는 출력 단 한 줄의 결과에 : 2014년 5월 14일 12시 23분 32초 라인
당황

더 좋은 방법이 있다고 확신하지만 tail -f /dev/ttyUSB0cat 또는 echo 대신 시도하십시오 . 계속 작동합니다. 내 시스템에서 이것을 테스트하는 방법을 몰랐습니다.
Joe

tail -f / dev / ttyUSB0은 while 루프의 유무에 관계없이 출력을 제공하지 않습니다. 귀하의 의견에 대한 tvm.
당황한
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.