Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
zsh与bash在for循环中的区别,zsh的方式是什么?_Bash_Shell_Zsh - Fatal编程技术网

zsh与bash在for循环中的区别,zsh的方式是什么?

zsh与bash在for循环中的区别,zsh的方式是什么?,bash,shell,zsh,Bash,Shell,Zsh,假设有一个简单的脚本 for file in `hadoop classpath | tr ':' ' ' | sort | uniq`; do echo $file; done hadoop classpath的原始输出如下所示(查找jar的文件夹列表): 如果我在BourneShell中运行上述脚本,结果如下(这将给出指定类路径中包含的所有JAR的唯一列表): 然而,在zsh中,我仍然得到: zsh %> for file in `hadoop classpath | tr ':'

假设有一个简单的脚本

for file in `hadoop classpath | tr ':' ' ' | sort | uniq`; do echo $file; done
hadoop classpath的原始输出如下所示(查找jar的文件夹列表):

如果我在BourneShell中运行上述脚本,结果如下(这将给出指定类路径中包含的所有JAR的唯一列表):

然而,在zsh中,我仍然得到:

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 Server 6.5版。

与Bourne shell不同,zsh在扩展参数后不执行文件名生成。也就是说,
$x
的意思正好是它所说的,变量
x
的值作为一个参数传递,没有拆分或文件名扩展。要强制拆分空白,请使用
${=x}
或调用
setopt sh_word_split
。要强制文件名扩展,请使用
${~x}
或调用
setopt glob_subst
。要防止zsh在目录不包含文件时抱怨,请使用
(N)
修饰符,该修饰符在模式持续时间内设置
NULL\u GLOB
选项

将所有这些结果合并为:

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

请注意,如果使用GNU排序(Linux上的默认值),
sort | uniq
可以缩短为
sort-u

首先将输出存储在变量上:

t=$(hadoop classpath | tr ':' ' ' | sort | uniq)
$()
优于反勾号。)

然后按照建议的
${~var}
格式运行循环

相当于

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

整个过程是一个参数扩展
${…}
:您可以在参数名称之外的更多内容上使用参数扩展,以使用参数扩展标志,而无需命名要处理的值。在本例中,我们将一些参数标志应用于
$(hadoop类路径)
的结果,它们是:

  • s/:/
    -在
    分隔符上将扩展名拆分为多个单词
  • o
    -按升序对生成的单词进行排序
  • u
    -仅展开每个唯一单词的第一个匹配项
然后您就有了
GLOB_SUBST
的问题:默认情况下,zsh不会对参数展开执行globbing。您可以使用
setopt GLOB_SUBST
全局更改此值,或使用
${~spec}
表单更改特定扩展:

for f in ${(s/:/ou)$(hadoop classpath)}; do echo $~f; done
或者,您可以在正在循环的扩展上启用
GLOB\u SUBST

for f in ${(s/:/ou)~$(hadoop classpath)}; do echo $f; done
并认识到整个循环是多余的:

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

还有一件事:我怀疑您只是将
sort
用作
uniq
的支柱。您不需要使用
o
参数扩展标志来实现每个路径名的一个副本,
u
将在不排序的情况下处理。

感谢您的宝贵提示,尽管它仍然不完全相同:这个脚本生成文件名块列表,而不是像bash那样的文件排序列表。@Ashalynd我想我看到了问题所在。我现在修改了答案,生成了一个单独条目的列表,而不是一个扩展块的列表。太好了,可以了!不过有一件小事:如果其中一个文件夹中碰巧没有文件(比如/usr/local/hadoop/contrib/capacity scheduler/*.jar),那么shell会抱怨:找不到匹配项:/usr/local/hadoop/contrib/capacity scheduler/*.jar,并且什么也不输出。因此,理想的做法是跳过没有文件的文件夹,但我想我要求的太多了:)@Ashalynd啊,是的,我已经修改了答案,使用扩展上的
(N)
修饰符来解决这个问题。如果我试图从shell运行它,zsh在设置t时会对行说“错误的赋值”。如果我试着从脚本运行它,它会显示关于${~t}部分的“错误替换”。啊,对不起,我的错误,我必须在脚本的开头指定zsh。尽管如此,没有运气,因为上面写着:找不到匹配项:/usr/local/hadoop/etc/hadoop/usr/local/hadoop/share/hadoop/common/lib/*/usr/local/hadoop/common/*/usr/local/hadoop/share/hdfs/usr/local/hadoop/share/hadoop/hdfs/hdfs/*/usr/local/hadoop/share/hdfs/*/usr/local/hadoop/share/lib/*/usr/local/hadoop/share/hadoop/thread/*/usr/local/hadoop/share/mapreduce/lib/*/usr/local/hadoop/mapreduce/*/usr/local/hadoop/contrib/capacity scheduler/*.jar一般来说,在bash中使用for循环的方式是不受欢迎的(尽管您明确希望字符串拆分和全局扩展,您的用例可能是个例外);你有没有注意到整个
| sort | uniq
的东西都是无用的,因为
sort
对行进行排序,但是
tr
输出仍然是一个输出?如果要对
hadoop类路径
输出进行排序,管道必须是
hadoop类路径| tr':''\n'| sort | uniq
${(s/:/ou)$(hadoop classpath)}
for f in ${(s/:/ou)$(hadoop classpath)}; do echo $~f; done
for f in ${(s/:/ou)~$(hadoop classpath)}; do echo $f; done
print -l ${(s/:/ou)~$(hadoop classpath)}