Perl One - Liners | Perl 명령 행 학습 3 - a 와 - F 매개 변수

9449 단어
Perl 명령 행 - a 인자 - F 인자
[지난 회 회고]
지난번 에 말 했 듯 이 -p-n 매개 변 수 는 예전 에 배 운 -e 매개 변 수 를 더 하면 많은 일 을 할 수 있 지만 편 의 를 위해 Perl 은 이런 파트너 조합의 매개 변 수 를 가지 고 있다. 바로 -a-F 이다.
[매개 변수 해석]
- a: 읽 은 $_ 을 분할 하여 @F 목록 에 저장 합 니 다. split / / , $_; 와 유사 합 니 다. 이 구분 자 는 -F 매개 변수 가 지정 한 것 입 니 다. 사실은 이 기능 은 awk 도구 와 비슷 합 니 다.
- F: -a 인 자 를 추가 할 때 구분자 (정규 표현 식 일 수 있 음) 를 지정 합 니 다. 빈 칸 을 구분자 로 하지 않 으 면 설정 합 니 다.
실례 설명
더 명확 한 설명 을 위해 서 는 예 를 들 어 터미널 이나 git for windows 를 엽 니 다.
입력
#                           ,      
echo "qwe asd zxc" | perl -n -a -F"\s+"-e '
  $" = "
"; foreach my $item (@F){ print "$item
"; } ' -------------------------------------- # qwe asd zxc

이번 의 예 는 이전의 예 보다 좀 복잡 하 니, 내 가 일일이 설명 하 겠 다.
  • echo 화면 에 qwe asd zxc 라 는 문자열 을 인쇄 합 니 다. 이 문자열 은 중간 에 빈 칸 에서 세 부분 으로 나 뉘 는데 각각 qwe, asd, zxc
  • 입 니 다.
  • echo 의 출력 이 파이프 에 들 어 갑 니 다 |
  • 한 줄 씩 읽 혔 다 (한 줄 밖 에 없어 서 바로 읽 었 다)
  • 읽 은 문자열 할당 perl
  • $_ 3 부 $_ 의 요구 에 따라 -a (더 블 따옴표 는 - F 매개 변수 가 붙 어 있 고 중간 에 빈 칸 이 없 음 을 주의 하 세 요) 의 지정 에 따라 \ s + (하나 이상 의 빈 칸 이나 탭 문자 로 구분 되 며 여기 도 '+' 로 바 꿀 수 있 습 니 다) -F 를 3 부 로 나 눌 수 있 습 니 다
  • qwe asd zxc
       ^   ^
       |   |
         
    
    #         \s+                     
    #     ,     
    
        /   /
    qwe/asd/zxc       @F      ('qwe','asd','zxc')
      /   /
    
  • 구 분 된 세 부 는 순서대로 존재 한다 $_ 목록 에
  • 목록 을 옮 겨 다 니 며 그 내용 을 인쇄 합 니 다
  • 사실 전에 배 운 매개 변 수 를 사용 하면 충분 하 다 고 말 할 수 있 습 니 다!예 를 들 면
    echo "qwe asd zxc" | perl -n -e '
        my @F = split /\s+/,$_;
        $" = "
    "; print "@F
    "; '

    근 데 왜 그 랬 을 까?사실 일반적인 텍스트 에 서 는 느끼 지 못 한 것 보다 Liux 나 mac 시스템 에서 텍스트 로 된 정보 가 많 습 니 다. 그리고 중간 에 보통 빈 칸 이나 탭 문자 로 구 분 됩 니 다. 예 를 들 어 df 명령 으로 디스크 의 사용 상황 을 봅 니 다.
    df
    ------------------------------------------
    #   
    Filesystem           1K-blocks      Used Available Use% Mounted on
    C:/Program Files/Git 104857596  63822260  41035336  61% /
    D:                   318168060 313664144 125465657  40% /d
    E:                    41942012  21699268  20242744  52% /e
    
    

    빈 칸 이나 탭 문자 로 구 분 된 선명 한 정보 형식 을 볼 수 있다.문제 가 생 겼 습 니 다. 이 두 개의 매개 변 수 를 이용 하여 우 리 는 일 을 해 볼 수 있 습 니 다.
    문제 1: 모든 디스크 를 추출 하고 인쇄 해 야 합 니까?
    한번 해 보 겠 습 니 다.
    df | perl -n -a -F"\s+" -e '
      print $F[0],"
    "; ' ------------------------------------------ # Filesystem C:/Program D: E:

    그런데 제목 은 제 가 원 하 는 게 아 닌 데 어떻게 빼 죠?여러 가지 방법 이 있어 요.
  • 특수 변수 사용 @F
  • @F 현재 읽 은 줄 수 를 뜻 합 니 다.
    df | perl -n -a -F"\s+" -e '
      #          ,     
      if($. == 1){
        next;
      }else{
        print $F[0],"
    "; } ' ------------------------------------------ # C:/Program D: E:
  • 리 눅 스 명령 의 힘 을 빌리다
  • # awk NR     ,    perl   $.       ,         
    df | perl -n -a -F"\s+" -e '
      print $F[0],"
    "; ' | awk 'NR>1{print $0}' ------------------------------------------ # C:/Program D: E:

    메모: 현실 디스크 에 있 을 때 $. 불완전 하 게 표 시 된 것 을 발 견 했 습 니 다. $. 만 표 시 했 습 니 다. 즉, 분리 되 었 습 니 다!!폴 더 는 빈 칸 을 사용 할 수 있 습 니 다 (특히 windows 아래 시스템 폴 더 C:/Program Files/Git. 정말 귀 찮 습 니 다). 이 럴 때 빈 칸 으로 구분 하면 조심해 야 합 니 다. 보통 Liux 와 mac 아래 에서 이런 상황 을 만 나 지 못 합 니 다.여기 서 시연 을 더욱 편리 하 게 한 후에 첫 번 째 설명 을 편리 하 게 하기 위해 서 나 는 CD 를 제거 했다.그러나 만약 에 확실히 CD 를 넣 어서 처리 해 야 한다 면 진행 할 수 있 습 니 다. 다만 좀 복잡 할 뿐 입 니 다. 여 기 는 제 가 서술 하지 않 고 글 말미 에 제 가 연 구 를 하 겠 습 니 다.
    문제 2: D 디스크 와 E 디스크 가 모두 사용 한 디스크 의 메모 리 를 계산 하려 고 합 니 다.
    #      ,   df         ,           @F  
    df | perl -n -a -F"\s+" -e '
    BEGIN{
      $total = 0;
    }
    chomp;
    #   C 
    if(m/^C:/){
      next;
    }
    if($. == 1){
      next;
    }else{
      $total = $total + $F[2];
    }
    END{
      print "total use : $total
    "; } ' ---------------------------------------------------- # total use : 335363412

    위 에 두 개의 특수 한 코드 블록 C:/ProgramC:/Program Files 을 사 용 했 습 니 다. 이 두 코드 블록 은 perl 의 단일 줄 프로그램 에서 두 가지 역할 을 설명 하 는 데 자주 사 용 됩 니 다.
    #                   #     
    _________________________________________________________
    BEGIN{              |       +++++++++       
        1;            |       +   1 +       1
    }                   |       +++++++++       
                        |
                        |       ---> ++++
                        |       ---> + +          
      2;              |       ---> + +        2
                        |       ---> +2 +
                        |       .... ++++
                        |
    END{                |       +++++++++         
        3;            |       +   3 +     3
    }                   |       +++++++++      
    _________________________________________________________
    

    사실 BEGIN{}END{} 블록 이 놓 인 순서 와 위 치 는 중요 하지 않다. 즉, 이렇게 할 수 있다 는 것 이다.
    #   1
    
    BEGIN{  
        1;
    }       
    END{    
        3;
    }  
      2;  
    ------------------
    #   2
    END{    
        3;
    }
      2;
    BEGIN{  
        1;
    } 
    ------------------
    #   3
      2; 
    BEGIN{  
        1;
    }       
    END{    
        3;
    } 
    

    사실 빈 칸 으로 구 분 된 것 을 제외 하고 우리 가 평소에 사용 하 는 엑셀 의 두 가지 형식 도 특정한 문자 로 구 분 된 것 이다.
  • CSV 파일: 쉼표 로 구 분 된 텍스트 파일
  • TSV 파일: 탭 문자 로 분 단 된 텍스트 파일
  • 이런 파일 에 대해 서 는 이 두 개의 매개 변 수 를 사용 하여 조합 하면 많은 일 을 절약 할 수 있 습 니 다. 그 렇 죠?
    #        123.csv
    #     txt    ,      csv   
    #    
    name,apple,banana,orange,grape,strawberry
    color,red,yellow,orange,purple,red
    
  • 예시 1
  • 목표: 첫 번 째 열, 즉 제목 을 출력 합 니 다.
    cat 123.csv | perl -n -a -F"," -e '
      print "$F[0]
    "; ' # name color
  • 예시 2
  • 목표: 몇 가지 색상 이 나 왔 는 지 계산
    cat 123.csv | perl -n -a -F"," -e '
      #       color     
      if($F[0] eq 'color'){
        #          
        shift @F;
        
        for my $color (@F){
          #              
          #                   
          #          
          #      ,    2
          $hash{$color}++;
        }
      }
      END{
        #   scalar          
        print "Total number of color type : ",scalar(keys %hash),"
    "; } ' --------------------------------------------- # Total number of color type : 4
  • 예제 3 목표: 아래 와 같은 방식 으로 인쇄 (사 이 는 쉼표 로 구분) 하 는데 이것 은 바로 목록 의 반전 이다. 이 예 는 약간 복잡 하 다. 이 예 는 의미 가 크 지 않다.하지만 여러 perl 단일 프로그램
  • 을 결합 했다.
    name,color
    apple,red
    banana,yellow
    orange,orange
    grape,purple
    strawberry,red
    
    
    #     
    cat 123.csv | perl -n -a -F"," -e '
    
      #          ,                    
      #       
      $F[-1] =~ s/\r*
    //; my $title = shift @F; my @items = @F; my $item_num = scalar(@items) unless defined $item_num; $title_num++; # # title push @title_list,$title; # # title $hash{$title} = \@items; END{ $" = ","; # print "@title_list
    "; # for my $row (0..$item_num-1){ for my $key (@title_list){ print $hash{$key}->[$row]; print ","; } print "
    "; } } ' | perl -p -e 's/,$//' ----------------------------------------------------- # name,color apple,red banana,yellow orange,orange grape,purple strawberry,red

    보충 설명
  • - a 와 - F 매개 변수의 순 서 는 중요 하지 않 지만 - e 매개 변수 앞 에 두 어야 합 니 다
  • - F 구분자 가 지 정 될 때 뒤의 구분자 가 - F 인 자 를 붙 여야 합 니 다. 중간 에 빈 칸 같은 것 이 없어 야 합 니 다. 그렇지 않 으 면 오류 가 발생 합 니 다
  • 탐구 하 다.
    위 에서 말 한 것 처럼 폴 더 에 빈 칸 이 있 을 때 가 있다 고 합 니 다. 위 에서 나타 난 BEGIN{} 분 리 된 상황 처럼 이렇게 처리 할 방법 이 없 습 니까?다시 한 번 END{} 의 출력 결 과 를 보 겠 습 니 다.
    df
    ------------------------------------------
    #   
    Filesystem           1K-blocks      Used Available Use% Mounted on
    C:/Program Files/Git 104857596  63822260  41035336  61% /
    D:                   318168060 313664144 125465657  40% /d
    E:                    41942012  21699268  20242744  52% /e
    
    

    빈 칸 으로 구분 하 는 것 은 통 하지 않 을 수 있 지만 생각 을 바 꾸 고 문자열 의 수량 에 따라 구분 할 수 있 습 니까?
    |-------------------|---------|---------|---------|----|----------|
    Filesystem           1K-blocks      Used Available Use% Mounted on
    C:/Program Files/Git 104857596  63822260  41035336  61% /
    D:                   318168060 313664144 125465657  40% /d
    E:                    41942012  21699268  20242744  52% /e
    

    각 열 에 대응 하 는 문자열 의 길이 (빈 칸 도 계 산 됩 니 다) 가 일치 하 는 것 을 볼 수 있 습 니 다!해 보다
    #               ,          
    #     
    export col=1
    df | perl -n -e '
      BEGIN{
        #          
        #        
        $col = $ENV{'col'};
      }
      if($. == 1){
        @title_slice = (22,11,11,11,5,11);
        next;
      }
      my $offset = 0;
      map {$offset+= $_} @F[0..$col-2] if $col-2 > 0;
      print substr($_,$offset,$title_slice[$col-1]-1) =~ s/\s*(.+?)\s*/$1/r,"
    "; ' # ,

    저작권 성명: 본 고 는 지식 공유 서명 - 비상 업적 사용 - 연역 금지 4.0 국제 허가 협의 (CC BY - NC - ND 4.0) 를 이용 하여 허가 합 니 다.

    좋은 웹페이지 즐겨찾기