我找不到使用 ZSH 内置拆分运算符执行此操作的正确语法:https://zsh.sourceforge.io/Guide/zshguide05.html
这有效,但我试图摆脱 echo / sed
for i in *;
do f=$(echo $i | sed 's/[-.]/ /g');
parts=(${(s: :)f}); echo $parts[1]; done
如何在表达式中指定字符集parts=(${(s: :)f});
?
我试图找到输入字符串的第一个字母数字子字符串。
答案1
这s[sep]
参数扩展标志只接受一个字符串(不必是单个字符),而不是一个模式。
您可以s
通过以下方式组合多个运算符嵌套扩展:
for file in *(N); do
parts=( ${(@s[-])${(s[.])file}} )
print -r The first part is $parts[1]
done
(另请注意(N)
全局限定符以避免当前工作目录中没有非隐藏文件时出现错误)。
或者你可以使用IFS 拆分为$=var
1:
IFS=.-
parts=( $=file )
请注意, whileparts=( ${(s[.])string} )
会丢弃空元素,IFS=.; parts=( $=string )
但不会,尽管您可以parts=($=string); parts=($string)
事后丢弃它们或使用匿名函数,例如(){ parts=($@); } $=string
.
或者,当您将所有字符替换为 1 并使用s[sep]
或 IFS 分割对其进行分割时,尽管您可以使用 ksh 样式${param//pattern/replacement}
或 csh 样式(使用histsubstpattern
在)$param:gs/pattern/replacement/
:
parts=( ${(s[.])file//[-...]/.} )
如果这只是您需要的第一个部分,您可以这样做:
first_part=${file%%[.-]*}
就像 ksh 中的语法来自 80 年代。
如果它是一个或多个alnums的第一个序列:
set -o extendedglob
first_sequence_of_alnums=${(MS)file##[[:alnum:]]##}
或者
if [[ $file =~ [[:alnum:]]+ ]]; then
first_sequence_of_alnums=$MATCH
else
print -ru2 "There are no alnums in $file"
fi
或者:
alnum_sequences=( ${(s[:])file//[^[:alnum:]]/:} )
if (( $#alnum_sequences > 0 )); then
first_sequence_of_alnums=$alnum_sequences[1]
else
print -ru2 "There are no alnums in $file"
fi
无论如何,如果你必须使用echo
,这应该是
echo -E - $file
如果没有-E
,反斜杠$file
可能会被破坏。如果没有,这对于诸如...之类-
的值不起作用$file
-n
-Eneene
print
:print -r -- $file
(或者print -r - $file
)。更重要的是不要忘记--
/-
与print
asprint
支持更多选项,其中一些可能存在危险。
1 请注意这是其他类似 Bourne 的 shell 在未加引号的参数扩展时默认执行的操作之一,通常被认为是一个错误特征(并且危险的一个!)。在 zsh 中,您必须显式请求分割,$=var
就像您必须显式请求通配符一样(也在其他 shell 中的未加引号的扩展上完成!)$~var
(或$=~var
两者)。