2014-07-15 1 views
3

간단한 스크립트가 있다고 가정합니다.zsh 대 forbash 루프의 차이점은 무엇입니까?

for file in `hadoop classpath | tr ':' ' ' | sort | uniq`; do echo $file; done 

hadoop classpath의 원래 출력 (항아리를 찾는 폴더의 목록) 다음과 같습니다 : 나는 Bourne 쉘 위의 스크립트를 실행하는 경우

zsh %> hadoop classpath 
/usr/local/hadoop/etc/hadoop:/usr/local/hadoop/share/hadoop/common/lib/*:/usr/local/hadoop/share/hadoop/common/*:/usr/local/hadoop/share/hadoop/hdfs:/usr/local/hadoop/share/hadoop/hdfs/lib/*:/usr/local/hadoop/share/hadoop/hdfs/*:/usr/local/hadoop/share/hadoop/yarn/lib/*:/usr/local/hadoop/share/hadoop/yarn/*:/usr/local/hadoop/share/hadoop/mapreduce/lib/*:/usr/local/hadoop/share/hadoop/mapreduce/*:/usr/local/hadoop/contrib/capacity-scheduler/*.jar 

하는 결과가 될 것입니다 (지정된 클래스 경로에 포함 된 모든 항아리의 고유 한 목록을 줄 것이다)이 같은 : zsh을에서

bash-4.1$ for file in `hadoop classpath | tr ':' ' ' | sort | uniq`; do echo $file; done 
/usr/local/hadoop/etc/hadoop 
/usr/local/hadoop/share/hadoop/common/lib/activation-1.1.jar 
/usr/local/hadoop/share/hadoop/common/lib/asm-3.2.jar 
/usr/local/hadoop/share/hadoop/common/lib/avro-1.7.4.jar 
/usr/local/hadoop/share/hadoop/common/lib/commons-beanutils-1.7.0.jar 
/usr/local/hadoop/share/hadoop/common/lib/commons-beanutils-core-1.8.0.jar 
/usr/local/hadoop/share/hadoop/common/lib/commons-cli-1.2.jar 
/usr/local/hadoop/share/hadoop/common/lib/commons-codec-1.4.jar 
... 

을하지만, 난 아직도 얻을 :

,369을
zsh %> for file in `hadoop classpath | tr ':' ' ' | sort | uniq`; do echo $file; done   
/usr/local/hadoop/etc/hadoop 
/usr/local/hadoop/share/hadoop/common/lib/* 
/usr/local/hadoop/share/hadoop/common/* 
/usr/local/hadoop/share/hadoop/hdfs 
/usr/local/hadoop/share/hadoop/hdfs/lib/* 
/usr/local/hadoop/share/hadoop/hdfs/* 
/usr/local/hadoop/share/hadoop/yarn/lib/* 
/usr/local/hadoop/share/hadoop/yarn/* 
/usr/local/hadoop/share/hadoop/mapreduce/lib/* 
/usr/local/hadoop/share/hadoop/mapreduce/* 
/usr/local/hadoop/contrib/capacity-scheduler/*.jar 

(즉, 클래스 패스의 폴더보다 더 많은 것).

호기심 때문에 디렉토리 목록을 zsh의 파일 정렬 목록으로 변환하는 방법은 무엇입니까?

해당 시스템은 Red Hat Enterprise Linux 서버 버전 6.5입니다.

+2

일반적으로 for 루프를 사용하면 bash에서이 방법을 사용할 수 없습니다 (비록 문자열 분할과 glob 확장을 명시 적으로 원하기 때문에 유스 케이스가 예외 일 수 있음). http://mywiki.wooledge.org/DontReadLinesWithFor –

+0

을 보아라. 전체'| 정렬 | uniq'는'sort'가 줄을 정렬했기 때문에 쓸모가 없지만'tr' 출력은 여전히 ​​하나의 줄에 있습니다. 'hadoop classpath' 출력을 정렬하고 싶다면 파이프 라인은'hadoop classpath | tr ':' '\ n'| 정렬 | uniq' –

답변

8

Bourne 쉘과 달리 zsh는 매개 변수를 확장 한 후에 파일 이름 생성을 수행하지 않습니다. 나는. $x은 정확히 무엇을 말하는지, 변수 x의 값은 분할 또는 파일명 확장없이 하나의 인수로 전달됩니다. 공백 분할을 강제 실행하려면 ${=x}을 사용하거나 setopt sh_word_split을 호출하십시오. 강제로 파일 이름을 확장하려면 ${~x}을 사용하거나 setopt glob_subst을 호출하십시오. 디렉토리에 파일이없는 경우 zsh에서 불평을하지 않게하려면 (N) 수정자를 사용하여 패턴 기간 동안 NULL_GLOB 옵션을 설정하십시오. 당신이 GNU 정렬 (리눅스의 기본)를 사용하는 경우 sort | uniqsort -u 단축 할 수 있다는

classpath=$(hadoop classpath | tr ':' ' ' | sort | uniq) 
for file in ${=~classpath}(N); do 
    echo $file 
done 

참고 :

이 모든 결과를 결합.

+0

훌륭한 팁을 가져 주셔서 감사합니다. 여전히 똑같은 것은 아니지만,이 스크립트는 bash처럼 정렬 된 파일 목록 대신 파일 이름 블록 목록을 생성합니다. – Ashalynd

+0

@Ashalynd 문제가 있다고 생각합니다. 이제 확장 된 청크 목록이 아닌 개별 항목 목록을 생성하는 답을 수정했습니다. – user4815162342

+0

멋진 작품! 하나의 작은 일 : 이러한 폴더 중 하나에 파일이 없으면 (예 : /usr/local/hadoop/contrib/capacity-scheduler/*.jar) 셸은 불평합니다 : 일치하는 항목이 없습니다 :/usr/local/hadoop/contrib/capacity-scheduler/*. jar를 실행하고 아무것도 출력하지 않습니다. 따라서 파일이없는 폴더를 건너 뛰는 것이 이상적이지만, 나는 너무 많이 요청하고있는 것 같다. – Ashalynd

0

스토어 먼저 변수 출력 :

t=$(hadoop classpath | tr ':' ' ' | sort | uniq) 

($()는 역 따옴표 선호된다.) user4815162342

for file in ${~t}; do 
    echo "$file" 
done 
+0

쉘에서 실행하려고하면 t가 설정된 경우 줄에 대해 "잘못된 할당"이라고 표시됩니다. 스크립트에서 실행하려고하면 $ {~ t} 부분에 대해 "잘못된 대체"라고 표시됩니다. – Ashalynd

+0

아, 죄송합니다, 제 잘못, 스크립트 시작 부분에 zsh를 지정해야했습니다. 그러나 일치하지 않는다 :/usr/local/hadoop/etc/hadoop/usr/local/hadoop/share/hadoop/common/lib/*/usr/local/hadoop/share/hadoop/common/*/usr/local/hadoop/share/hadoop/hdfs/usr/local/hadoop/share/hadoop/hdfs/lib/*/usr/local/hadoop/share/hadoop/hdfs/*/usr/local/hadoop/share/hadoop/yarn/lib/*/usr/local/hadoop/share/hadoop/yarn/*/usr/local/hadoop/share/hadoop/mapreduce/lib/*/usr/local/hadoop/share/hadoop/mapreduce/* /usr/local/hadoop/contrib/capacity-scheduler/*.jar – Ashalynd

0

a로 제안

그럼 ${~var} 형식 루프를 실행할 "zsh-native"에 해당하는

$(hadoop classpath | tr ':' '\n' | sort | uniq) 

${(s/:/ou)$(hadoop classpath)} 

모든 일이 매개 변수 확장 ${...}입니다 : 당신은 당신이 처리 할 값의 이름을 지정하지 않고 매개 변수 확장 플래그 사용하기 위해, 단지 매개 변수 이름보다 더 많은 것들에 매개 변수 확장을 사용할 수 있습니다.이 경우, 우리는 $(hadoop classpath)의 결과에 어떤 매개 변수 플래그를 적용, 그들은 위치 :

  • s/:/ -하게 분할 :에 여러 단어로 확장 구분 기호
  • o - 오름차순
  • 의 결과 단어를 정렬
  • u - 각각의 고유 한 단어의 첫 번째 발생을 확장
  • 다음

당신이 GLOB_SUBST의 문제 : zsh을에 globbing을 수행하지 않습니다 paramet 기본적으로 확장이 가능합니다. 당신은 setopt GLOB_SUBST과 함께 전 세계적으로이를 변경하거나 특정 확장에 대한 ${~spec} 양식을 사용 할 수 있습니다 : 또는

for f in ${(s/:/ou)$(hadoop classpath)}; do echo $~f; done 

을, 당신은 확장에 GLOB_SUBST을 가능하게 할 수는 이상 반복하고 있습니다 :

for f in ${(s/:/ou)~$(hadoop classpath)}; do echo $f; done 

및 실현 전체 루프는 불필요 :

print -l ${(s/:/ou)~$(hadoop classpath)} 

한 가지 더 : 난 당신이 단지로 sort을 사용 의심 버클은 uniq입니다. o 매개 변수 확장 플래그가 각 경로 이름의 복사본 하나만을 얻기 위해 필요하지 않습니다. u은 정렬없이 대처합니다.

관련 문제