Unix 명령에서 이스케이프된 구분 기호 문자를 방지하려면 어떻게 해야 합니까?

Unix 명령에서 이스케이프된 구분 기호 문자를 방지하려면 어떻게 해야 합니까?

물결표(~)로 구분된 필드의 합계를 구해야 합니다. 내가 가진 문제는 내 데이터에도 구분 기호가 이스케이프되어 있다는 것입니다.

1~CEO~ashok\~kumar~1000

위의 세 번째 필드에서 볼 수 있듯이 피하고 싶은 구분 기호를 이스케이프 처리했습니다. 나는 이것을 처리하지 않는 아래 명령을 실행하고 있습니다.

$ cat test.out|awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'

데이터를 다음과 같이 가정합니다 test.out.

1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000

따라서 내 출력은 4000이어야 합니다. 그러나 현재 내 명령으로는 3000만 얻습니다!

답변1

로 처리하기 전에 이스케이프된 구분 기호를 다른 것으로 변경하세요 awk. 이는 다음을 사용하여 수행할 수 있습니다 sed.

$ cat test.out| sed 's/\\~/=/g' | \
    awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
4000

그리고 종종 그렇듯이 다음 cat은 필요하지 않습니다.

$ sed 's/\\~/=/g' test.out | awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'

답변2

다음은 사용하지 않는 대안입니다 awk.

$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+ | bc
4000

위의 내용은 세 번째 열에서 sed이스케이프된 물결표를 바꾸는 데 사용됩니다. \~그런 다음 를 사용하여 숫자의 4번째 열을 선택한 다음 더하기 기호( ) cut로 구분되도록 재구성 할 수 있습니다.+

$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+
1000+2000+1000

그런 다음 이 문자열은 이진 계산기에 제공되어 bc합산됩니다.

답변3

perl이스케이프를 처리하기 위한 일반적인 방법은 PCRE 및 대체 정규식 연산자를 역추적 없음 연산자와 결합하여 사용하는 것입니다 . GNU에서는 다음과 같습니다 grep.

grep -Po '(?>(?:\\.|.)*?~){3}\K(?:\\.|[^~])*' << \EOF
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
4~field2~field3\\~10000~field5-note-the-escaped-backslash-not-tilde
5~a\~b\~c\~no-4th-field-here
EOF

이는 다음을 제공합니다:

1000
2000
1000
10000

(평상시와 합산할 수 있음 awk '{s+=$0};END{print s}')

GNU를 사용하면 sed다음과 같이 할 수도 있습니다.

sed -rn 's/((\\.|[^\~])*~){3}((\\.|[^~])*).*/\3/p'

GNU를 사용하면 필드를 이스케이프 문자나 물결표나 백슬래시가 아닌 문자의 시퀀스로 정의 awk할 수 있습니다 .FPAT

awk -v FPAT='(\\\\.|[^\\\\~])*' '{print $4}'

답변4

이는 awk에서는 약간 어색합니다(구분 기호를 변경하기 위해 소스를 전처리할 수 있지만 입력에 나타날 수 없는 다른 문자나 문자 시퀀스를 알아야 하는 경우는 제외). 당신이 할 수 있는 한 가지는 전체 줄을 읽은 다음 줄을 마사지하여 구분 기호로 줄바꿈을 얻는 것입니다(줄바꿈은 줄에 나타날 수 없는 유일한 것입니다).

awk 'BEGIN {FS="\n"}
{
    gsub("~", "\n");
    gsub("\\\n", "~");
    gsub("\\\\", "\\");
    $0 = $0;
    print $4;
}'

관련 정보