같은 줄에 중첩된 구분 기호가 있는 텍스트 파일을 구문 분석합니다.

같은 줄에 중첩된 구분 기호가 있는 텍스트 파일을 구문 분석합니다.

btrfs가 .btrfs라는 파일에 배치하는 btrfs 정리 통계를 구문 분석하고 싶습니다 /var/lib/btrfs/scrub.status.<uuid>. 파일은 실제로 키/값 쌍으로 구성됩니다. 여기서 키와 값은 세미콜론으로 구분되고 튜플은 파이프("|") 문자로 구분됩니다.

scrub status:1
b5872f47-c87e-47ac-b036-4f2725cf6dc6:1|data_extents_scrubbed:4996799|tree_extents_scrubbed:1436139|data_bytes_scrubbed:156663988224|tree_bytes_scrubbed:23529701376|read_errors:0|csum_errors:0|verify_errors:0|no_csum:733729|csum_discards:0|super_errors:0|malloc_errors:0|uncorrectable_errors:0|corrected_errors:0|last_physical:202959224832|t_start:1597847400|t_resumed:0|duration:67|canceled:0|finished:1

마지막으로, 예를 들어 각 키/값 쌍을 별도의 줄에 내보내고 싶습니다(이는 Prometheus 측정항목으로 사용됩니다).

scrub status 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
[...]

나는 sed이 중첩 구문 분석을 /accomplishing 사용해 보았지만 awk지금까지 실패했습니다.

이를 달성하는 방법에 대한 조언을 주시면 감사하겠습니다!

답변1

  • 모든 sed:

    sed 's/:/ /g;s/|/\
    /g' file
    
  • GNU sed:

    sed 's/:/ /g;s/|/\n/g' file
    

여기서는 :공백 |과 개행 문자로 모든 것을 변경합니다.

awk를 사용하면 레코드 구분 기호를 파이프 문자로 설정한 다음 :공백으로 바꿀 수 있습니다.

awk 'BEGIN{RS="|"}{gsub(":"," ");print}' file

답변2

다중 문자 RS에 GNU awk 사용:

$ awk -v RS='[|]|\n$' -F':' '{$1=$1}1' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

|또한 위의 솔루션 은 RS를 .

답변3

노력하다:

$ awk -F'|' '{for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376

작동 방식:

  • -F'|'필드 구분 기호를 로 설정합니다 |.

  • {for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}각 필드를 반복하고 공백을 바꾸고 :필드를 인쇄합니다.

답변4

tr이것이 문자를 변환하는 가장 빠른 방법이 아닌가 ?

$ <file tr ':|' ' \n'

scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

물론 tr1바이트 문자에만 작동합니다. 이는 :및 에 대해서는 문제가 되지 않습니다 |.

sed(멀티바이트 문자(GNU/ATT) 사용 가능)와 동등한 기능은 다음과 같습니다.

<file sed 'y/:|/ \n/'

관련 정보