awk를 사용하여 두 위치 인수 사이를 인쇄하는 방법

awk를 사용하여 두 위치 인수 사이를 인쇄하는 방법

awk를 사용하여 위치 매개변수 뒤의 모든 내용을 인쇄하는 방법이 있나요? 다음 명령으로 인쇄하고 싶은 것은 "p4 p5 p6 p7"입니다.

echo p1 p2 p3 p4 p5 p6 p7 | awk '{print $4...}'

또한 두 위치 매개변수 사이에 인쇄하는 것도 가능합니까? 다음은 "p4 p5 p6"을 인쇄합니다.

echo p1 p2 p3 p4 p5 p6 p7 | awk '{print $4...$6}'

정규식을 사용하고 다음을 입력하는 것을 피하고 싶습니다: awk '{print $4" "$5" "$6}'

답변1

awk(일종의 루프를 사용하지 않고) 이 작업을 수행하는 것은 불가능하지만 perl가능합니다.

그러나 perl배열은 0부터 시작합니다(그리고 awk배열 인덱싱은 1부터 시작합니다).

예를 들어 다음과 같이 자동 분할을 위해 perl' 옵션을 사용합니다.-aawk

$ echo p1 p2 p3 p4 p5 p6 p7 | perl -lane 'print "@F[3..$#F]";'
p4 p5 p6 p7 

$ echo p1 p2 p3 p4 p5 p6 p7 | perl -lane 'print "@F[2,4,6]";'
p3 p5 p7

$ echo p1 p2 p3 p4 p5 p6 p7 | perl -lane 'print "@F[1..3]";'
p2 p3 p4

참고: -lPerl의 줄 끝 자동 처리를 켜고 -n자동 출력 없이 한 줄씩 입력을 처리하는 루프로 래핑합니다(sed의 -n 옵션과 유사합니다. -p동일한 작업을 수행하지만 다음 내용을 자동으로 인쇄합니다. 각 입력 줄이 확인되었습니다. 및/또는 나머지 스크립트에 의해 수정됨). 바라보다 man perlrun.

배열 및 배열 분할에 대한 자세한 내용은 man perldata또는를 참조하세요.perldoc perlvar

배열 조각은 큰따옴표로 묶인 문자열 안에 인쇄되므로 $"aka 값을 사용하여 $LIST_SEPARATOR배열 요소를 구분합니다. 큰따옴표로 묶인 문자열 외부에서 인쇄/사용되는 경우 요소 사이에 구분 기호가 전혀 없습니다. LIST_SEPARATOR를 확인 man perlvar하거나 perldoc perlvar검색하세요.

-F마지막으로, 필드 구분 기호가 공백(PCRE에서)이 아닌 경우 Perl의 options 을 사용 \s+하거나 직접 분할하세요. 예를 들어

$ echo "p1:p2:p3:p4:p5:p6:p7" | perl -F: -lane 'print "@F[0..4]";'
p1 p2 p3 p4 p5

$ echo "p1:p2:p3:p4:p5:p6:p7" | perl -lne '@F=split /:/; print "@F[0..4]";'
p1 p2 p3 p4 p5

답변2

매개변수가 공백으로 확실하게 구분되어 있는 경우 다음을 사용할 수 있습니다 cut.

echo p1 p2 p3 p4 p5 p6 p7 | cut -d' ' -f4-   # For p4 onwards
echo p1 p2 p3 p4 p5 p6 p7 | cut -d' ' -f4-6  # For p4 to p6

인수를 공백으로 구분하려면 인수를 구문 분석하는 방식이 awk확실히 더 복잡해집니다. 제가 말하는 내용과 위의 내용이 원하는 효과를 항상 얻지 못할 수 있는 방법에 대한 예를 보려면 다음을 시도해 보세요.

printf '%s   ' p1 p2 p3 p4 p5 p6 p7 | cut -d' ' -f4-
printf '%s   ' p1 p2 p3 p4 p5 p6 p7 | cut -d' ' -f4-6

cut치료 되고 있는 모습을 보실 수 있습니다구분 기호로 공백을 사용하는 것이지 이와 같은 구분 기호로 연속 공백을 사용하는 것이 아닙니다 awk. awkfor 루프를 사용하여 원하는 것을 강제할 수 있습니다 .

echo p1 p2 p3 p4 p5 p6 p7 | awk '{for (a=4;a<=NF;a++) {printf "%s ", $a} printf "\n"}'

그러나 이렇게 하면 줄 끝에 후행 공백이 남습니다. 이 문제는 해결될 수 있지만 상황은 점점 더 혼란스러워질 것입니다. 요구 사항에 따라 이 cut명령이 괜찮을 수도 있습니다.

답변3

awk의 분할 기능을 사용하여 수행하는 방법은 다음과 같습니다(이전 답변에 따르면 for 루프가 필요함).

설명하다:

 "sub_0"         - variable to contain desired output ($0 substring)

 "beg"           - 1st desired field (references 4th element in "pn_ary" array)
                   (external "$beg" shell variable passed into awk (internal "beg" variable)

 "end"           - # of fields in $0 (split function loads each field in $0 as a "pn_ary[n]" element ("1-n"))

 "split(s,a,sep) - "s": string, "a": array, "sep": seperator (splits "s" per "sep", loads "a")
                   ("split" returns # of elements loaded into "pn_ary" array into "end" variable)

 "FS"            - awk system Field Seperator variable

 "[:graph:]"     - Posix bracket expression for visible ASCII chars in range "[\x21-\x7E]"   

통사론:

 beg="4"

 echo "p1 p2 p3 p4 p5 p6 p7" |\

 awk '{sub_0="";end=split($0,pn_ary,FS)
       for (i=beg;i<=end;i++) {sub_0=sub_0""FS""pn_ary[i]}     
       print substr(sub_0,match(sub_0,"[:graph:]"))
      }' beg="$beg"

산출:

p4 p5 p6 p7

관련 정보