2014-07-27 3 views
8

나는 UNIX 쉘의 맵 기능으로 xargs을 생각해 보았다. filter 기능이란 무엇입니까?xargs가 map이면 필터 란 무엇입니까?

편집 : 좀 더 명확해야 할 것처럼 보입니다.

단일 문자열을 매개 변수로 사용하고 종료 코드 0 또는 1을 반환하는 프로그램을 제출해야한다고 가정 해 봅시다.이 프로그램은 허용되는 문자열에 대한 조건 자로 작동합니다.

예를 들어 문자열 매개 변수를 파일 경로로 해석하고 "이 파일이 존재합니까?"라는 조건을 정의 할 수 있습니다. 이 경우, 프로그램은 test -f 일 수 있으며, 주어진 문자열의 경우 파일이 존재하면 0으로 종료하고 그렇지 않으면 1로 종료합니다.

또한 문자열을 전달해야합니다. , 예를 들어, 내 파일 시스템에 존재 만 경로를 포함

/etc/apache2/apache2.conf 
/foo/bar/baz 
/etc/hosts 

지금, 나는 새로운 파일, ~/existing_paths을 만들 포함하는 파일 ~/paths이있을 수 있습니다. 내 경우에는, 그게 내가의 ~/paths 파일에 읽기 술어 test -f에 의해 그 라인을 필터링하고, ~/existing_paths 출력을 작성하여이 작업을 수행 할 수

/etc/apache2/apache2.conf 
/etc/hosts 

될 것이다.

xfilter COMMAND [ARG]... 

어느, 표준 입력의 각 행 L에 대한 COMMAND [ARG]... L를 호출합니다 : 그것은 내가 찾고 있어요 가설 프로그램 xfilter입니다

cat ~/paths | xfilter test -f > ~/existing_paths 

: 같은 xargs 유추으로이 보일 것이다 종료 코드가 0이면 L을 인쇄하고 그렇지 않으면 아무 것도 인쇄하지 않습니다.

  • 존재에 의해 filepaths의 목록을 필터링 할 수있는 방법을 :

    명확하게하기 위해, 내가 찾고 있지 않다. 그것은 구체적인 예입니다.

  • 어떻게 이러한 프로그램을 작성하십시오. 나는 그걸 할 수있어.
중 하나를 찾고

I 오전 :

  • 기존의 구현, xargs 같은, 또는
  • 이 존재하지 않는 이유에 대한 명확한 설명
+1

효과가 없으므로 ** fork ** Nt exit-status를 기반으로하는 파일 만 출력합니다. 앞서 말했듯이, 어떤 언어 (bash, perl, C)로도 작성하는 것이 간단하지만 효과적이지는 않습니다. 훨씬 더 효과적인 것은 몇 가지 명령 (상황에 따라 적절한 도구)을 직접 사용하여 _STDIN_을 읽을 수 있고 zilion 시간으로 입력 _을 필터링 할 수 있습니다. ** fork/exec ** exit-status 명령. 여러 번 'xargs'도 가장 효과적인 방법이 아닙니다. (파일 목록이 길어지면 1_000_000 줄을 상상해보십시오. 밀리언 포크는 할 수있는 최선의 방법이 아닙니다 ...) 그리고 필요한 경우 (알고있는 것처럼) 3 행 배시 기능입니다. – jm666

+3

@ jm666은 " "당신은"공연자 "를 의미합니다. 나는 공연에 관심이 없으며, 표현력에 관심이 있습니다. – jameshfisher

답변

1

당신 awkfilterreduce 기능을 수행 할 수 있습니다.

필터 :

awk 'NR % 2 { $0 = $0 " [EVEN]" } 1' 

감소 :

awk '{ p = p + $0 } END { print p }' 
+1

고마워요.하지만'xargs'는 매개 변수로 일반적인 쉘 명령을 가지고 있습니다.이 명령은 입력 행을 맵핑하는 함수입니다. 예를 들어,'filter'는 입력 행에 대한 술어 (예를 들어, 리턴 코드가 0인지 아닌지)에 따라 쉘 명령을 사용해야합니다. 당신의 예제에서, 술어는'awk'-speak에서만 정의됩니다. – jameshfisher

+0

@ jameshfisher 당신이 필요로하는 것은 제가 추측하는 껍질입니다. – konsolebox

+0

[이] (http://stackoverflow.com/questions/255898/how-to-iterate-over-arguments-in-bash-script)와 같은 의미가 확실하지 않습니다. – jameshfisher

3

그래서 개봉이 찾고 :

reduce( compare( filter(map(.. list())))) 

list | map | filter | compare | reduce 
로 rewiritten 할 수있는

bash의 주력은 파이프 라이닝이므로 특별한 filter 및/또는 reduce 명령이 필요하지 않습니다.

find mydir -type f -print | xargs grep -H '^[0-9]*$' | cut -d: -f 2 | sort -nr | head -1 
^------list+filter------^ ^--------map-----------^ ^--filter--^ ^compare^ ^reduce^ 
:
  • 지도
  • 필터
  • 상상
  • 을 줄일

    • 목록 : 사실 거의 모든 유닉스는 하나 (또는 ​​그 이상)의 기능에 역할을 할 수 명령

      테스트 케이스 만들기 :

      mkdir ./testcase 
      cd ./testcase || exit 1 
      for i in {1..10} 
      do 
          strings -1 < /dev/random | head -1000 > file.$i.txt 
      done 
      mkdir emptydir 
      

      는 당신은 디렉토리 testcase 이름 얻을 것이다,이 디렉토리에 10 개 파일과 하나의 디렉토리는

      각 파일이 일부 라인은 임의의 문자열 1,000 선을 포함
      emptydir file.1.txt file.10.txt file.2.txt file.3.txt file.4.txt file.5.txt file.6.txt file.7.txt file.8.txt file.9.txt 
      

      이제 실행 숫자 만 포함 명령

      find testcase -type f -print | xargs grep -H '^[0-9]*$' | cut -d: -f 2 | sort -nr | head -1 
      

      그리고 각 파일에서 가장 큰 숫자 전용 줄을 얻을 수 있습니다 : 42.

      분해 (물론, 이것은 이것은 단지 데모하고,보다 효율적으로 수행 할 수 있습니다) :

      find testcase -type f -print 그래서 모든 평범한 파일을 인쇄 할 것이다, LIST (파일 만 감소). OUPUT는 :

      testcase/file.1.txt 
      testcase/file.10.txt 
      testcase/file.2.txt 
      testcase/file.3.txt 
      testcase/file.4.txt 
      testcase/file.5.txt 
      testcase/file.6.txt 
      testcase/file.7.txt 
      testcase/file.8.txt 
      testcase/file.9.txt 
      

      xargs grep -H '^[0-9]*$' MAP 으로 목록의 각 파일에 대한 grep 명령을 실행합니다. grep은 일반적으로 필터과 같이 사용합니다 (예 : command | grep).하지만 이제는 (xargs와 함께) 입력 (파일 이름)이 (숫자 만 포함 된 행)로 변경됩니다. 출력, 많은 라인이 좋아 : 라인의

      testcase/file.1.txt:1 
      testcase/file.1.txt:8 
      .... 
      testcase/file.9.txt:4 
      testcase/file.9.txt:5 
      

      구조 : filename colon number, 그래서 순수한 필터를 호출 숫자 만 원하는 어떤 각 라인 cut -d: -f2에서 파일 이름을 제거합니다.이제이 감소 (가장 큰 수를 얻는)는 sort -nr 종류의 모든 수를 숫자로 그 출력은 같은 그래서, 순서 (내림차순) 역

      1 
      8 
      ... 
      4 
      5 
      

      : 그것은 같은 많은 라인을 출력

      42 
      18 
      9 
      9 
      ... 
      0 
      0 
      

      head -1은 첫 번째 줄 (가장 큰 숫자)을 인쇄합니다. 물론

      , 당신은/자신의 목록/필터 /지도를 작성할 수 bash 프로그래밍 구조 (루프, 조건 등)와 직접 기능을 감소하거나 perl, 특수 언어 awk 같은 sed 원하는 fullblown 스크립트 언어를 사용할 수있다 "언어"또는 dc (rpn) 등.

      같은 특수 필터 명령을 갖는지도 xargs 경우 직접

      list | cut 
      
    4

    를 사용할 수 있기 때문에

    list | filter_command cut -d: -f 2 
    

    이 필요하지 않습니다 간단을, 필터는 ... 여전히 xargs.

    예 : 목록 현재 디렉토리에있는 파일 및 필터링 비 실행 파일 :

    ls | xargs -I{} sh -c "test -x '{}' && echo '{}'" 
    

    이 만들 수있는 편리한 저점 A (비 생산 준비) 기능 : 또는

    xfilter() { 
        xargs -I{} sh -c "$* '{}' && echo '{}'" 
    } 
    ls | xfilter test -x 
    

    , GNU Parallel을 통한 병렬 필터 구현을 사용할 수 있습니다.

    ls | parallel "test -x '{}' && echo '{}'"