직렬 포트에 들어오는 스트림이 있으며 초당 약 한 번 새 줄이 나타납니다.
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