awk로 첫 번째 필드를 제외한 모든 것을 인쇄


108

다음과 같은 파일이 있습니다.

AE  United Arab Emirates
AG  Antigua & Barbuda
AN  Netherlands Antilles
AS  American Samoa
BA  Bosnia and Herzegovina
BF  Burkina Faso
BN  Brunei Darussalam

그리고 순서를 뒤집고 $ 1을 제외한 모든 것을 먼저 인쇄 한 다음 $ 1을 인쇄합니다.

United Arab Emirates AE

"필드 1을 제외한 모든"트릭을 어떻게 할 수 있습니까?


2
안녕하세요 @cfisher, 여분의 공간없이 루프 앵글없이 할 수 있습니다.
— Juan Diego Godoy Robles 2014

답변:


91

$1작업을 할당 하면 선행 공백이 남습니다.awk '{first = $1; $1 = ""; print $0, first; }'

열 수를 찾아 NF루프에서 사용할 수도 있습니다.


2
완전히 게으른 사람들을 위해; 여기에 klashxx의 코드가 있습니다.
— Serge Stroobandt 2015 년

1
큰. sed로 선행 공간을 제거했습니다. awk {'first = $1; $1=""; print $0'}|sed 's/^ //g'
— Thyag

일반 모드에서 'Ctrl + V Gd'를 눌러 VIM을 사용하면 공간이 쉽게 제거됩니다.
— Santi

107

$1=""Ben Jackson이 언급했듯이 공백을 남기므로 for루프를 사용하십시오 .

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

따라서 문자열이 "one two three"이면 출력은 다음과 같습니다.

둘
셋

결과를 한 행에 표시하려면 다음과 같이 할 수 있습니다.

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

이렇게하면 "둘 셋"이됩니다.


4
그리고 여분의 후행 공백
— NeronLeVelu

2
사용하기 더 좋은 방법 : awk '{for(i=2;i<=NF;i++){ printf("%s",( (i>2) ? OFS : "" ) $i) } ; print ;}' 어느 것 : 필드 2를 NF에 인쇄하고 필요에 따라 출력 필드 구분자를 추가합니다 (즉, $ 2 이전 제외). 마지막 인쇄는 현재 줄 인쇄를 끝내기 위해 마지막 줄 바꿈을 추가합니다. 당신이 FS / OFS을 변경하면 하나가 작동합니다 (즉, 항상 "공간"되지 않습니다)
— 올리비에 Dulac

두 번째는 나를 위해 정말 잘 작동했습니다. 첫 번째는 그다지 많지 않습니다. 이유가 확실하지 않습니다. 전체 텍스트를 잘랐습니다.
— 음성

72

다음 옵션 cut과 함께 명령을 사용하십시오 --complement.

$ echo a b c | cut -f 1 -d ' '
a
$ echo a b c | cut -f 1,2 -d ' '
a b
$ echo a b c | cut -f 1 -d ' ' --complement
b c

2
awk와 관련된 질문에 대답하지 않았지만 awk가 중복 공백을 제거하고 cut은 그렇지 않기 때문에 이것이 가장 유용하다는 것을 알았습니다.
— Fmstrat 2014 년

19
echo a b c | cut -d' ' -f 2- 인 대안
— 루이스

2
니스 - --complement 지원하지 않는 맥에 @Luis 솔루션 작품
— metadaddy

21

아마도 가장 간결한 방법은 다음과 같습니다.

$ awk '{$(NF+1)=$1;$1=""}sub(FS,"")' infile
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

설명:

$(NF+1)=$1: "새"마지막 필드 생성기.

$1="": 원래 첫 번째 필드를 null로 설정

sub(FS,""): 처음 두 작업 후 {$(NF+1)=$1;$1=""}sub를 사용하여 첫 번째 필드 구분 기호를 제거합니다. 최종 인쇄는 암시 적입니다.


13
awk '{sub($1 FS,"")}7' YourFile

첫 번째 필드와 구분 기호를 제거하고 결과를 인쇄합니다 ( 70이 아닌 값이므로 $ 0 인쇄).


베스트 답변! 찬성. 그냥 사용하는 것과 어떻게 다른 1가요? 이 패턴의 사용법이 궁금하고 이해하고 싶었습니다. 감사!
— Abhijeet Rastogi

10
awk '{ saved = $1; $1 = ""; print substr($0, 2), saved }'

첫 번째 필드를로 설정하면 의 시작 부분에의 ""단일 복사본이 남습니다 . 단일 문자 (기본적으로 단일 공백) 라고 가정하면 . 그런 다음 저장된 사본을 추가합니다 .OFS$0OFSsubstr($0, 2)$1


6

Perl 솔루션에 개방적이라면 ...

perl -lane 'print join " ",@F[1..$#F,0]' file

한 공백의 입력 / 출력 구분 기호가있는 간단한 솔루션으로 다음을 생성합니다.

United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

다음은 약간 더 복잡합니다.

perl -F`  ` -lane 'print join "  ",@F[1..$#F,0]' file

입력 / 출력 구분 기호가 두 개의 공백이라고 가정합니다.

United Arab Emirates  AE
Antigua & Barbuda  AG
Netherlands Antilles  AN
American Samoa  AS
Bosnia and Herzegovina  BA
Burkina Faso  BF
Brunei Darussalam  BN

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

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

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

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

  • -F autosplit 수정 자,이 예에서는 ''(두 공백)로 분할합니다.

  • -e 다음 perl 코드를 실행하십시오.

@F는 각 줄에있는 단어의 배열이며, 0
$#F으로 시작하는 인덱스 는 단어의 수 @F
@F[1..$#F]입니다. 요소 1부터 마지막 ​​요소까지
@F[1..$#F,0]의 배열 조각입니다. 요소 1부터 마지막 ​​요소와 요소 0을 더한 배열 조각입니다.


1
나는 그것을 실행하고 끝에 추가 번호를 가지고 있었으므로이 버전을 사용했습니다. perl -lane 'shift @F; print join "", @F '
— Hans Poo

2

gawk (적어도)의 필드 구분 기호는 문자 일뿐만 아니라 문자열 일 수 있습니다 (정규식 일 수도 있음). 데이터가 일관되면 다음과 같이 작동합니다.

awk -F "  " '{print $2,$1}' inputfile

큰 따옴표 사이에 두 개의 공백이 있습니다.


당면한 상황에 대한 최선의 대답이지만 기술적으로 이것은 첫 번째 필드를 제외한 모든 것을 인쇄하는 방법에 대한 질문에 대한 대답이 아닙니다.
— Dan Molding

@DanMoulding : 국가 코드를 구분하기 위해 두 개의 공백을 사용하여 파일이 일관되고 두 개의 공백이 함께 발생 하지 않는 한 내 대답 은 질문을 해결합니다.
— 추후 공지가있을 때까지 일시 중지되었습니다.

2
이 질문에 착수 한 사람들은 첫 번째 필드를 제외한 모든 것을 인쇄하는 방법을 알고 싶어하기 때문에 여기에 온다 (질문 제목 참조). 그것이 내가 여기에 착륙 한 방법입니다. 귀하의 대답은 첫 번째 필드와 두 번째 필드를 인쇄하는 방법을 보여줍니다. 이것이 OP의 특정 상황에 대한 최상의 솔루션 일 수 있지만 첫 번째 필드를 제외한 모든 것을 인쇄하는 방법에 대한 일반적인 문제를 해결하지는 못합니다.
— Dan Molding

2

awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'


2

모든 레코드를 다음 레코드로 이동하고 마지막 레코드를 첫 번째 레코드로 설정하겠습니다.

$ awk '{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' file
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

설명

  • a=$1 첫 번째 값을 임시 변수에 저장하십시오.
  • for (i=2; i<=NF; i++) $(i-1)=$i N 번째 필드 값을 (N-1) 번째 필드에 저장합니다.
  • $NF=a 첫 번째 값 ($1 )을 마지막 필드에 .
  • {}1awk기본 작업 을 수행 하기위한 true 조건 : {print $0}.

이렇게하면 다른 필드 구분 기호가있는 경우 결과도 좋습니다.

$ cat c
AE-United-Arab-Emirates
AG-Antigua-&-Barbuda
AN-Netherlands-Antilles
AS-American-Samoa
BA-Bosnia-and-Herzegovina
BF-Burkina-Faso
BN-Brunei-Darussalam

$ awk 'BEGIN{OFS=FS="-"}{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' c
United-Arab-Emirates-AE
Antigua-&-Barbuda-AG
Netherlands-Antilles-AN
American-Samoa-AS
Bosnia-and-Herzegovina-BA
Burkina-Faso-BF
Brunei-Darussalam-BN

1

첫 번째 찌르는 것은 특정 경우에 효과가있는 것 같습니다.

awk '{ f = $1; i = $NF; while (i <= 0); gsub(/^[A-Z][A-Z][ ][ ]/,""); print $i, f; }'

1

옵션 1

일부 버전의 awk에서 작동하는 솔루션이 있습니다.

awk '{ $(NF+1)=$1;$1="";$0=$0;} NF=NF ' infile.txt

설명:

       $(NF+1)=$1                          # add a new field equal to field 1.
                  $1=""                    # erase the contents of field 1.
                        $0=$0;} NF=NF      # force a re-calc of fields.
                                           # and use NF to promote a print.

결과:

United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

그러나 이전 버전의 awk에서는 실패 할 수 있습니다.


옵션 2

awk '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt

그건:

awk '{                                      # call awk.
       $(NF+1)=$1;                          # Add one trailing field.
                  $1="";                    # Erase first field.
                        sub(OFS,"");        # remove leading OFS.
                                    }1'     # print the line.

지워야하는 것은 FS가 아니라 OFS입니다. $ 1 필드가 서명되면 라인이 다시 계산됩니다. 그러면 모든 FS 실행이 하나의 OFS로 변경됩니다.


그러나 OFS를 변경하면 분명히 알 수 있듯이 해당 옵션조차도 여러 구분 기호로 실패합니다.

awk -v OFS=';' '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt

해당 줄은 다음을 출력합니다.

United;Arab;Emirates;AE
Antigua;&;Barbuda;AG
Netherlands;Antilles;AN
American;Samoa;AS
Bosnia;and;Herzegovina;BA
Burkina;Faso;BF
Brunei;Darussalam;BN

이는 FS 실행이 하나의 OFS로 변경되고 있음을 나타냅니다.
이를 피하는 유일한 방법은 필드 재 계산을 피하는 것입니다.
재 계산을 피할 수있는 한 가지 기능은 sub입니다.
첫 번째 필드를 캡처 한 다음 sub를 사용하여 $ 0에서 제거한 다음 둘 다 다시 인쇄 할 수 있습니다.

옵션 3

awk '{ a=$1;sub("[^"FS"]+["FS"]+",""); print $0, a;}' infile.txt
       a=$1                                   # capture first field.
       sub( "                                 # replace: 
             [^"FS"]+                         # A run of non-FS
                     ["FS"]+                  # followed by a run of FS.
                            " , ""            # for nothing.
                                  )           # Default to $0 (the whole line.
       print $0, a                   # Print in reverse order, with OFS.


United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

FS, OFS를 변경하거나 구분 기호를 더 추가하더라도 작동합니다.
입력 파일이 다음으로 변경된 경우 :

AE..United....Arab....Emirates
AG..Antigua....&...Barbuda
AN..Netherlands...Antilles
AS..American...Samoa
BA..Bosnia...and...Herzegovina
BF..Burkina...Faso
BN..Brunei...Darussalam

그리고 명령은 다음과 같이 변경됩니다.

awk -vFS='.' -vOFS=';' '{a=$1;sub("[^"FS"]+["FS"]+",""); print $0,a;}' infile.txt

출력은 다음과 같습니다 (여전히 구분 기호 유지).

United....Arab....Emirates;AE
Antigua....&...Barbuda;AG
Netherlands...Antilles;AN
American...Samoa;AS
Bosnia...and...Herzegovina;BA
Burkina...Faso;BF
Brunei...Darussalam;BN

명령은 여러 필드로 확장 될 수 있지만 최신 awks 및 --re-interval 옵션이 활성화 된 경우에만 가능합니다. 원본 파일에 대한이 명령 :

awk -vn=2 '{a=$1;b=$2;sub("([^"FS"]+["FS"]+){"n"}","");print $0,a,b;}' infile.txt

다음을 출력합니다.

Arab Emirates AE United
& Barbuda AG Antigua
Antilles AN Netherlands
Samoa AS American
and Herzegovina BA Bosnia
Faso BF Burkina
Darussalam BN Brunei

1

다른 Perl 솔루션에 열려있는 경우 :

perl -ple 's/^(\S+)\s+(.*)/$2 $1/' file

0

sed 옵션도 있습니다 ...

 sed 's/\([^ ]*\)  \(.*\)/\2 \1/' inputfile.txt

설명 ...

Swap
\([^ ]*\) = Match anything until we reach a space, store in $1
\(.*\)    = Match everything else, store in $2
With
\2        = Retrieve $2
\1        = Retrieve $1

더 자세히 설명 ...

s    = Swap
/    = Beginning of source pattern
\(   = start storing this value
[^ ] = text not matching the space character
*    = 0 or more of the previous pattern
\)   = stop storing this value
\(   = start storing this value
.    = any character
*    = 0 or more of the previous pattern
\)   = stop storing this value
/    = End of source pattern, beginning of replacement
\2   = Retrieve the 2nd stored value
\1   = Retrieve the 1st stored value
/    = end of replacement

0

또 다른 방법 ...

... 이것은 FS와 NF를 통해 필드 2를 다시 결합하고 입력 한 줄당 한 줄을 출력합니다.

awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'

나는 이것을 git과 함께 사용하여 내 작업 디렉토리에서 어떤 파일이 수정되었는지 확인합니다.

git diff| \
    grep '\-\-git'| \
    awk '{print$NF}'| \
    awk -F"/" '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'

-3

cat 명령을 사용하는 또 다른 쉬운 방법

cat filename | awk '{print $2,$3,$4,$5,$6,$1}' > newfilename

이것은 동적 접근 방식이 아니기 때문에 반대 투표를했습니다. 이를 통해 인수의 수를 알고 데이터가 일관 적이라고 가정해야합니다. 데이터는 거의 일관성이 없으며 접근 방식은 대부분의 경우이를 고려해야합니다.
— xh3b4sd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.