awk 명령을 사용하여 n~m 필드를 지우는 방법은 무엇입니까?

awk 명령을 사용하여 n~m 필드를 지우는 방법은 무엇입니까?

AWK를 사용하여 다음 문제를 해결하고 싶습니다.

sed나 Perl과 같은 언어를 사용하여 다른 솔루션을 구현할 수 있다면 그것도 크게 감사하겠습니다.

입력은 다음과 같습니다.

U,N,UNIX,000,A,5
N,P,SHELL,111,B,6
I,M,UNIX,222,C,7
X,Y,BASH,333,D,8
P,R,SCRIPT,444,E,9

내가 원하는 출력은 다음과 같습니다.

U,N,,,A,5
N,P,,,B,6
I,M,,,C,7
X,Y,,,D,8
P,R,,,E,9

또한 참고하십시오:행당 총 필드 수를 모릅니다. 필드 3과 4는 비워두어야 한다는 것만 알고 있습니다.

답변1

명령에서 n부터 m까지의 모든 필드를 비례적으로 비우려면 awk값을 하드코딩해서는 안 됩니다. "for" 루프를 사용해야 합니다.

awk 'BEGIN { FS = ","; OFS = ","} {for (i = 3; i <= 4; i++) { $i = "" }; print}' inputfile

다른 범위를 지우고 싶다면 위 코드에서 "3"과 "4" 값을 조정하세요.


설명하다:

BEGIN { ... }블록은 파일의 모든 행을 보기 전에 처리됩니다.

OFS출력 필드 구분자를 설정하고, FS입력 필드 구분자를 설정합니다. 우리는 그것들이 쉼표가 되기를 원합니다.

루프는 forC 구문과 같습니다. 이 경우 3 및 4에 대해 다음을 수행합니다 { code block }.i

$i이는 쉘 구문과 완전히 다르다는 점을 언급할 가치가 있습니다 . 쉘 스크립트에서 $변수 값을 확장 하려면 변수 이름 앞에 접두어를 붙여야 합니다 . in.in awk자체는 해당 값(이 경우 3 또는 4)으로 awk확장되고 그 뒤에 숫자 표현이 옵니다.i$대지그 번호 위치에서요. 따라서 번째 필드는 빈 문자열로 $i = ""설정됩니다 .i

그런 다음 print인수가 없는 명령은 기본적으로 전체 줄을 인쇄합니다. 기본적으로 이전 명령으로 구분된 줄과 이전 명령으로 수정된 줄의 모든 필드를 가져와 모두 인쇄하고 FS개행 문자로 구분한 다음 끝에 개행 문자를 붙입니다.OFS


해당하는 더 짧은 명령:

위 명령이 스크립트에 포함된 경우 가장 명확하고 확장하기 쉬운 명령이라고 생각합니다. 무엇을 하고 있는지 매우 명확하고 읽기 쉽습니다. 또한 통화를 사용하거나 전환할 때 awk자동으로 수행할 수 없는 작업은 변경 없이 독립형 스크립트로 분할할 수 있습니다 . (물론 이것이 사용하지 말아야 할 이유는 아닙니다. 단지 주의할 점일 뿐입니다.)-v-Fawk

특히 일회성 사용의 경우 다음을 사용합니다.

awk -F, -v OFS=, '{for (i = 3; i <= 4; i++) { $i = "" }; print}' inputfile

스위치 설정 -F의 값입니다 FS. 이 스위치를 사용하면 명령줄에서 변수 값을 설정할 수 있습니다 -v.awk

보다 일반적으로 이 스위치는 셸 변수를 awk 변수로 전달하고 명령줄 옵션을 사용하여 스크립트 파일에서 추출된 독립 실행형 스크립트의 런타임 동작을 변경하는 데 -v유용합니다 .-v myawkvar="$myshellvar"awk-f scriptname

답변2

</path/to/in_file awk -v 'FS=,' -v 'OFS=,' '{$3=$4=""; print}'

설명하다

  • </path/to/in_file: 파일을 표준으로 읽어옵니다.
  • -v 'FS=,' -v 'OFS=,': 파일 구분 기호와 출력 파일 구분 기호를 로 설정합니다 ,.
  • '{$3=$4=""; print}': 세 번째와 네 번째 필드를 공백으로 설정한 다음 전체 줄을 인쇄합니다(약어:제이슨 라이언).

답변3

sed 's/\([^,]*,\)\{2\}/,,/2' <in >out

U,N,,,A,5
N,P,,,B,6
I,M,,,C,7
X,Y,,,D,8
P,R,,,E,9

이렇게 하면 쉼표로 구분된 연속된 두 필드 집합의 두 번째 항목이 두 개의 쉼표로 대체됩니다.

다음과 같이 할 수도 있습니다.

sed 's/[^,]*//4;s///3' <in >out

...쉼표가 아닌 문자 시퀀스의 네 번째 및 세 번째 항목을 아무것도 대체하지 않습니다.

@Wildcard처럼 확장 가능한 루프를 사용하세요.

sed -e:t -e'/\n\{2\}/!s/\(\n*\)[^,]*./\n\1/3;/\n$/!tt' -e's///;y/\n/,/'

...또는...

sed -e:t -e's/\n$//;s/\n/&/2;to'  \
    -e's/\(\n*\)[^,]*./\1\n/3;tt' \
    -e:o -ey/\\n/,/

...어디3블랭킹을 시작하려는 필드 번호입니다.,구분 기호입니다.2모두 비워두려는 필드의 수입니다.

어떻게 쓰던 간에...

sed "$script" <<""
U
N,P
I,M,UNIX
X,Y,BASH,333
P,R,SCRIPT,444,E,9

U
N,P
I,M,
X,Y,,
P,R,,,E,9

...대신 리터럴 개행 문자를 사용해야 할 수도 있지만 n.../\1\n/3.

답변4

펄을 사용할 수 있어요

perl -F, -lane '@F[2,3]=""; print join ",", @F'

이는 -a자동 분할을 사용하고 -F쉼표를 필드 구분 기호로 사용합니다. -nSTDIN을 행별로 반복합니다. 그런 다음 -e필드 2와 3을 대체하는 스크립트를 지정하고(Perl은 처음부터 시작함) 결과를 인쇄합니다.

-l줄 끝을 암시적으로 제거하고 추가합니다.

관련 정보