Moreutils ts로 파이프 포트에 들어오는 스트림이 있으며

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

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가 원치 않는 라인을 제거하도록 할 수는 있지만 제거하기 전에 타임 스탬프를 작성하는 것은 잘못된 접근법이어야합니다.

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



답변

질문에 직접 대답하기 위해서는 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

답변

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