awk를 사용하여 n에서 마지막까지 모든 열을 인쇄


310

이 줄은 두 번째 필드에 공백이 생길 때까지 작동했습니다.

svn status | grep '\!' | gawk '{print $2;}' > removedProjs

awk를 $ 2 이상으로 인쇄하는 방법이 있습니까? (더 이상 열이 없어 질 때까지 $ 3, $ 4 ..?)

Cygwin이있는 Windows 환경 에서이 작업을 수행한다고 추가해야한다고 가정합니다.


11
옆으로, grep | awk은 반 패턴입니다 – 당신은awk '/!/ { print $2 }'
트리플 리

3
유닉스 "잘라 내기"가 더 쉽다 ...svn status | grep '\!' | cut -d' ' -f2- > removedProjs
roblogic


@tripleee : 당신이 이것을 언급하게되어 너무 기쁩니다-나는 그것을 어디서나 보는 것에 좌절했습니다!
Graham Nicholls

답변:


489

첫 번째 열을 제외한 모든 열을 인쇄합니다.

awk '{$1=""; print $0}' somefile

두 개의 첫 번째 열을 제외한 모든 열을 인쇄합니다.

awk '{$1=$2=""; print $0}' somefile

93
gotcha

5
나는 실용적인 접근 방식을 좋아합니다. cat을 사용할 필요는 없지만 awk 명령 뒤에 파일 이름을 넣으십시오.
kon

45
@raphinesse 당신은 그것을 해결할 수 있습니다awk '{$1=""; print substr($0,2)}' input_filename > output_filename
themiurgo

6
공백이 아닌 구분 기호로는 작동하지 않으며 공백으로 바꿉니다.
Dejan

3
공백이 아닌 분리 문자의 경우 쉼표와 같이 OFS (Output Field Separator)를 지정할 수 있습니다 awk -F, -vOFS=, '{$1=""; print $0}'. 초기 분리 문자로 끝납니다 ( $1여전히 빈 문자열로 포함됨). 당신은 sed그래도 그것을 제거 할 수 있습니다 :awk -F, -vOFS=, '{$1=""; print $0}' | sed 's/^,//'
cherdt

99

cut을 사용하여 더 간단한 답변 을 가진 중복 질문이 있습니다 .

 svn status |  grep '\!' | cut -d\  -f2-

-ddelimeter (space)-f지정하고 열 목록을 지정합니다 (모두 2로 시작)


"-b"를 사용하여 위치를 지정할 수도 있습니다 (N 번째 문자부터).
다카 틴

참고로, 비록이 수행 같은 작업은 AS awk버전에 맞춰 버퍼링 문제가 cut되는 awk:이없는 stackoverflow.com/questions/14360640/...
sdaau

24
멋지고 단순하지만주의 할 점이 awk있습니다. 여러 개의 인접한 공간 문자를 처리합니다. 단일 분리기 로서 cut; 또한-현재로서는 문제가되지 않지만 cut문자 그대로의 단일 문자 만 허용합니다. 구분 기호로 사용하지만 awk정규 표현식을 허용합니다.
mklement0

이를 바탕으로 stackoverflow.com/a/39217130/8852408 은이 솔루션이 그리 효율적이지 않을 수 있습니다.
FcknGioconda

85

for-loop를 사용하여 $ 2에서 $ NF까지의 인쇄 필드 (라인의 필드 수를 나타내는 내장 변수)를 반복 할 수 있습니다.

편집 : "print"는 개행을 추가하므로 결과를 버퍼링해야합니다.

awk '{out=""; for(i=2;i<=NF;i++){out=out" "$i}; print out}'

또는 printf를 사용하십시오 :

awk '{for(i=2;i<=NF;i++){printf "%s ", $i}; printf "\n"}'

그래서 나는 이것을 시도했지만 뭔가 빠졌다고 생각합니다. 여기 내가 svn status 한 것입니다 | grep '\!' | gawk '{for (i = 1; i <= $ NF; i ++) print $ i "";}'> removedProjs
Andy

print는 개행을 추가하므로 결과를 버퍼링해야합니다. 내 편집을 참조하십시오.
VeeArr

1
필드를 반복하는 방법을 보여주기 때문에이 답변이 더 좋습니다.
Edward Falk

3
인쇄에 공백을 사용하려면 출력 레코드 구분 기호를 변경하십시오. awk '{ORS = ""; for (i = 2; i <NF; i ++) print $ i} 'somefile
Christian Lescuyer

3
공간이 항상 너무 많습니다. 이것은 잘 작동 : '{for(i=11;i<=NF-1;i++){printf "%s ", $i}; print $NF;}'없음 선행 또는 후행 공백.
Marki

24
awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'

내 대답은 VeeArr 중 하나를 기반으로 하지만 두 번째 열 (및 나머지)을 인쇄하기 전에 공백으로 시작한 것을 알았습니다. 평판 포인트가 하나뿐이므로 댓글을 달 수 없으므로 여기에 새로운 답변이됩니다.

두 번째 열로 "out"으로 시작한 다음 다른 열을 모두 추가하십시오 (있는 경우). 두 번째 열이있는 한 잘 진행됩니다.


2
훌륭합니다. 또한 out 변수 앞의 $도 제거했습니다.
Alexis Wilke 1

15

awk가있는 대부분의 솔루션은 공백을 남깁니다. 여기서 옵션은 그 문제를 피합니다.

옵션 1

간단한 절단 솔루션 (단일 구분 기호로만 작동) :

command | cut -d' ' -f3-

옵션 2

awk를 다시 계산하면 첫 번째 필드를 제거하여 남은 선행 공간 (OFS)을 제거 할 수 있습니다 (일부 awk 버전에서 작동).

command | awk '{ $1=$2="";$0=$0;} NF=NF'

옵션 3

로 서식이 지정된 각 필드를 인쇄 printf하면 더 많은 제어가 가능합니다.

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in"|awk -v n=2 '{ for(i=n+1;i<=NF;i++) printf("%s%s",$i,i==NF?RS:OFS);}'
3 4 5 6 7 8

그러나 모든 이전 답변은 필드 사이의 모든 반복 FS를 OFS로 변경합니다. 그렇게하지 않는 몇 가지 옵션을 만들어 봅시다.

옵션 4 (권장)

앞의 필드와 구분자를 제거하기위한 sub가있는 루프.
그리고 공간 대신 ​​FS 값을 사용하십시오 (변경 가능).
휴대 성, 그리고 OFS에 FS의 변화를 트리거하지 않습니다 참고 : (가) ^[FS]*선행 공백이있는 입력을 허용하는 것입니다.

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in" | awk '{ n=2; a="^["FS"]*[^"FS"]+["FS"]+";
  for(i=1;i<=n;i++) sub( a , "" , $0 ) } 1 '
3     4   5   6 7     8

옵션 5

다음과 같이 여분의 공백을 추가하지 않는 솔루션을 빌드하고 gensubGNU awk 의 기능 을 사용하여 기존 공백을 보존하는 것이 가능합니다.

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          { print(gensub(a""b""c,"",1)); }'
3     4   5   6 7     8 

카운트가 지정된 필드 그룹을 바꾸는 데 사용될 수도 있습니다 n.

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          {
            d=gensub(a""b""c,"",1);
            e=gensub("^(.*)"d,"\\1",1,$0);
            print("|"d"|","!"e"!");
          }'
|3     4   5   6 7     8  | !    1    2  !

물론 이러한 경우 OFS는 라인의 두 부분을 분리하는 데 사용되며 필드의 후행 공백은 여전히 ​​인쇄됩니다.

참고 : [FS]* 입력 라인에 선행 공백을 허용하는 데 사용됩니다.


13

나는 개인적으로 위에서 언급 한 모든 답변을 시도했지만 대부분은 약간 복잡하거나 잘못되었습니다. 내 관점에서 가장 쉬운 방법은 다음과 같습니다.

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
  1. 여기서 -F ""는 awk가 사용할 구분자를 정의합니다. 필자의 경우 공백은 awk의 기본 구분 기호입니다. 이것은 -F ""를 무시할 수 있음을 의미합니다.

  2. 여기서 NF는 총 필드 / 컬럼 수를 정의합니다. 따라서 루프는 4 번째 필드부터 마지막 ​​필드 / 열까지 시작합니다.

  3. 여기서 $ N은 N 번째 필드의 값을 검색합니다. 따라서 print $ i는 루프 카운트에 따라 현재 필드 / 열을 인쇄합니다.


4
문제는 각 필드를 다른 줄에 인쇄합니다.
mveroone

아무것도 끝에 이것을 추가하는 것을 멈추지 않습니다 :-)`| tr '\ n' ''`
koullislp

3
늦은 비트하지만, AWK는 '{에 대해는 (내가 5 = 나는 <= NF; 내가 ++) {printf와 "% S",} 난을 $}'
plitter


7

이것은 나에게 너무 자극적이었다. 나는 앉아서 cutGNU Awk 3.1.7로 테스트 한 비슷한 필드 스펙 파서를 작성했다 .

첫째,라는 새로운 awk는 라이브러리 스크립트를 작성 pfcut예와,

sudo nano /usr/share/awk/pfcut

그런 다음 아래 스크립트를 붙여넣고 저장하십시오. 그 후 사용법은 다음과 같습니다.

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-4"); }'
t1 t2 t3 t4

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("2-"); }'
t2 t3 t4 t5 t6 t7

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

이 모든 것을 입력하지 않으려면 최선의 방법으로 할 수 있습니다 (그렇지 않으면 awk로 시작할 때 자동으로 사용자 함수로드?-유닉스 및 리눅스 스택 교환 참조 )는에 별칭을 추가하는 것입니다 ~/.bashrc. 예를 들어

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases

... 그러면 다음과 같이 전화 할 수 있습니다.

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk-pfcut '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

pfcut스크립트 소스는 다음과 같습니다 .

# pfcut - print fields like cut
#
# sdaau, GNU GPL
# Nov, 2013

function spfcut(formatstring)
{
  # parse format string
  numsplitscomma = split(formatstring, fsa, ",");
  numspecparts = 0;
  split("", parts); # clear/initialize array (for e.g. `tail` piping into `awk`)
  for(i=1;i<=numsplitscomma;i++) {
    commapart=fsa[i];
    numsplitsminus = split(fsa[i], cpa, "-");
    # assume here a range is always just two parts: "a-b"
    # also assume user has already sorted the ranges
    #print numsplitsminus, cpa[1], cpa[2]; # debug
    if(numsplitsminus==2) {
     if ((cpa[1]) == "") cpa[1] = 1;
     if ((cpa[2]) == "") cpa[2] = NF;
     for(j=cpa[1];j<=cpa[2];j++) {
       parts[numspecparts++] = j;
     }
    } else parts[numspecparts++] = commapart;
  }
  n=asort(parts); outs="";
  for(i=1;i<=n;i++) {
    outs = outs sprintf("%s%s", $parts[i], (i==n)?"":OFS); 
    #print(i, parts[i]); # debug
  }
  return outs;
}

function pfcut(formatstring) {
  print spfcut(formatstring);
}

사용 cut하지 않는 것 같습니다awk
roblogic

5

# 2에서 시작하는 열을 인쇄합니다 (출력은 처음에 후행 공백이 없음).

ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'

1
+필드 뒤에 둘 이상의 공백이있을 수 있으므로 공백 뒤에 추가해야합니다 ( awk여러 개의 인접한 공백을 단일 구분 기호로 처리). 또한 awk선행 공백을 무시하므로 정규 표현식을로 시작해야합니다 ^[ ]*. 구분자로 공간을 사용하면 솔루션을 일반화 할 수도 있습니다. 예를 들어, 다음은 세 번째 필드에서 모든 것을 반환합니다. awk '{sub(/^[ ]*([^ ]+ +){2}/, ""); print $0}'그러나 임의의 필드 구분 기호를 사용하면 까다로워집니다.
mklement0

5

이게 효과가 있을까요?

awk '{print substr($0,length($1)+1);}' < file

그래도 공백이 남습니다.


4
echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

이것은 awk를 사용하여 마지막 필드를 제외한 모든 것을 인쇄합니다.


3

이것이 내가 모든 권장 사항에서 선호하는 것입니다.

6 번째 열부터 마지막 ​​열까지 인쇄

ls -lthr | awk '{out=$6; for(i=7;i<=NF;i++){out=out" "$i}; print out}'

또는

ls -lthr | awk '{ORS=" "; for(i=6;i<=NF;i++) print $i;print "\n"}'

2

임의의 delimeter로 인쇄 된 특정 열이 필요한 경우 :

awk '{print $3 "  " $4}'

열 # 3 열 # 4

awk '{print $3 "anything" $4}'

col # 3anythingcol # 4

따라서 열에 공백이 있으면 두 개의 열이되지만 구분 기호를 사용하거나 구분하지 않고 연결할 수 있습니다.


2

펄 솔루션 :

perl -lane 'splice @F,0,1; print join " ",@F' file

다음과 같은 명령 줄 옵션이 사용됩니다.

  • -n 입력 파일의 모든 줄을 반복하고 모든 줄을 자동으로 인쇄하지는 않습니다.

  • -l 처리하기 전에 줄 바꿈을 제거하고 나중에 다시 줄 바꿈

  • -a자동 분할 모드 – 입력 라인을 @F 배열로 분할합니다. 공백으로 기본 분할

  • -e 펄 코드를 실행

splice @F,0,1 @F 배열에서 열 0을 깨끗하게 제거합니다.

join " ",@F 각 요소 사이에 공백을 사용하여 @F 배열의 요소를 결합합니다.


파이썬 솔루션 :

python -c "import sys;[sys.stdout.write(' '.join(line.split()[1:]) + '\n') for line in sys.stdin]" < file


1

잘리지 않는 줄 부분을 다시 포맷하지 않으려면 내가 생각할 수있는 가장 좋은 해결책은 다음과 같이 대답합니다.

awk를 사용하여 특정 숫자 다음에 모든 열을 인쇄하는 방법은 무엇입니까?

주어진 필드 번호 N 이전의 내용을 잘라 내고 필드 번호 N을 포함하여 원래 줄 간격을 유지하면서 나머지 줄을 모두 인쇄합니다 (재 포맷하지 않음). 필드의 문자열이 줄의 다른 곳에 나타나는 경우에는 문제가되지 않습니다.

함수를 정의하십시오.

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

그리고 이것을 다음과 같이 사용하십시오 :

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

출력은 후행 공백을 포함하여 모든 것을 유지합니다

특별한 경우 :

svn status | grep '\!' | fromField 2 > removedProjs

파일 / 스트림에 줄 중간에 개행 문자가 포함되어 있지 않으면 (다른 레코드 구분 기호를 사용할 수 있음) 다음을 사용할 수 있습니다.

awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

첫 번째 경우는 드문 16 진 문자 번호 1을 포함하는 파일 / 스트림에서만 실패합니다.


0

이것은 Bash를 사용하고 있고 버리려는 요소만큼 많은 'x'를 사용할 수 있고 여러 공간이 이스케이프되지 않으면 무시합니다.

while read x b; do echo "$b"; done < filename

0

펄 :

@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
        print "$i\n";

}

1
이것은 N 번째 열에서 끝까지 인쇄 요구 사항을 일반화하는 질문에 대답하지 않습니다 .
roaima

0

awk함수는 $0에서 begin까지의 필드를 포함하는 하위 문자열을 반환 합니다 end.

function fields(begin, end,    b, e, p, i) {
    b = 0; e = 0; p = 0;
    for (i = 1; i <= NF; ++i) {
        if (begin == i) { b = p; }
        p += length($i);
        e = p;
        if (end == i) { break; }
        p += length(FS);
    }
    return substr($0, b + 1, e - b);
}

필드 3부터 모든 것을 시작하려면 :

tail = fields(3);

$03 ~ 5 개의 필드를 다루는 섹션을 얻으려면 :

middle = fields(3, 5);

b, e, p, i함수 매개 변수 목록의 넌센스는 awk지역 변수를 선언 하는 방법입니다.


0

필드가 여러 공백으로 구분되는 상황에 대해 제안 된 답변을 확장하고 싶습니다 . OP가 사용하지 않는 이유 cut라고 생각합니다.

OP가에 대해 묻는 것을 알고 awk있지만 sed여기 에서 접근 방식이 작동합니다 (예 : 열을 5 번째에서 마지막으로 인쇄하는 예).

  • 순수한 sed 접근

    sed -r 's/^\s*(\S+\s+){4}//' somefile

    설명:

    • s/// 대체를 수행하는 표준 방법으로 사용됩니다
    • ^\s* 줄의 시작 부분에서 연속되는 공백과 일치
    • \S+\s+ 데이터 열을 의미합니다 (공백 문자가 아닌 공백 문자).
    • (){4} 패턴이 4 번 반복됨을 의미합니다.
  • sed와 컷

    sed -r 's/^\s+//; s/\s+/\t/g' somefile | cut -f5-

    연속 된 공백을 단일 탭으로 바꾸면됩니다.

  • tr 및 cut : 옵션을 tr사용하여 연속 문자 를 짜는 데 사용할 수도 있습니다 -s.

    tr -s [:blank:] <somefile | cut -d' ' -f5-

-1

Awk 예제는 복잡해 보입니다. 여기 간단한 Bash 쉘 구문이 있습니다.

command | while read -a cols; do echo ${cols[@]:1}; done

n 번째 열은 0부터 세는 곳 1은 어디 입니까?


이 파일의 내용 ( in.txt) 이 주어지면 :

c1
c1 c2
c1 c2 c3
c1 c2 c3 c4
c1 c2 c3 c4 c5

출력은 다음과 같습니다.

$ while read -a cols; do echo ${cols[@]:1}; done < in.txt 

c2
c2 c3
c2 c3 c4
c2 c3 c4 c5

-1

awk처음 몇 열을 추출하고 나머지를 인쇄하고 싶었 기 때문에 여기에 제시된 솔루션에 만족하지 못했습니다 perl. 다음 코드는 처음 두 열을 추출하고 나머지는 그대로 표시합니다.

echo -e "a  b  c  d\te\t\tf g" | \
  perl -ne 'my @f = split /\s+/, $_, 3; printf "first: %s second: %s rest: %s", @f;'

Chris Koknatperl솔루션 과 비교할 때의 이점 은 실제로 입력 문자열에서 처음 n 개의 요소 만 분리된다는 것입니다. 줄의 나머지 부분은 전혀 분리되지 않으므로 완전히 손상되지 않습니다. 내 예제는 공백과 탭이 혼합되어 있음을 보여줍니다.

추출해야하는 열의 양을 변경하려면 3예제에서를 n + 1로 바꾸십시오 .


-1
ls -la | awk '{o=$1" "$3; for (i=5; i<=NF; i++) o=o" "$i; print o }'

이 답변 에서 나쁘지는 않지만 자연 간격이 사라졌습니다.
그런 다음 이것을 이것과 비교하십시오 :

ls -la | cut -d\  -f4-

그러면 차이가 나타납니다.

심지어 ls -la | awk '{$1=$2=""; print}'기반으로하는 대답은 서식을 보존하지 않습니다 지금까지 최선을 투표했다.

따라서 다음을 사용하고 처음에는 명시적인 선택적 열을 허용합니다.

ls -la | cut -d\  -f1,4-

모든 공간도 열로 계산되므로 예를 들어 아래에서 열 1과 3은 비어 있고 2는 INFO이고 4는 다음과 같습니다.

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f1,3

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f2,4
INFO 2014-10-11
$

-1

서식이 지정된 텍스트를 원하면 명령을 echo로 묶고 $ 0을 사용하여 마지막 필드를 인쇄하십시오.

예:

for i in {8..11}; do
   s1="$i"
   s2="str$i"
   s3="str with spaces $i"
   echo -n "$s1 $s2" | awk '{printf "|%3d|%6s",$1,$2}'
   echo -en "$s3" | awk '{printf "|%-19s|\n", $0}'
done

인쇄물:

|  8|  str8|str with spaces 8  |
|  9|  str9|str with spaces 9  |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |

-9

340 표로 가장 많이 반대되는 답변으로 인해 5 분 동안 목숨을 잃었습니다! 이것을지지하기 전에이 답변을 시도한 사람이 있습니까? 별로. 완전히 쓸모없는.

IP 주소가있는 5 달러 이후에 더 많은 텍스트가 있거나 텍스트가없는 로그가 있습니다. $ 5 이후에 IP 주소부터 라인 끝까지 모든 것이 필요합니다. 내 경우에는 이것이 awk 프로그램이 아니라 awk oneliner가 아니기 때문에 awk는 문제를 해결해야합니다. 가장 많이 투표되었지만 완전히 틀린 답을 사용하여 처음 4 개의 필드를 제거하려고 할 때 :

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'

그것은 틀리고 쓸모없는 반응을 뱉어냅니다 (증명하기 위해 [..]를 추가했습니다).

[    37.244.182.218 one two three]

substr 과이 잘못된 대답을 결합하는 일부 제안도 있습니다. 그 합병증은 개선입니다.

대신 컷 포인트와 awk가 필요할 때까지 열의 너비를 고정하면 정답은 다음과 같습니다.

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{printf "[%s]\n", substr($0,28)}'

원하는 출력을 생성합니다.

[37.244.182.218 one two three]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.