对于练习,我写了一个由元字符组成的表达式,最多匹配3个大写字符。
实施例
a -> match
A -> match
Ab -> match
AbC -> match
AbCd -> match
...
ABCD -> no match, 4 uppercase chars
这是我想出来的,但我觉得我可以缩短它
ls @(!(*[A-Z]*)|*[A-Z]*|*[A-Z]*[A-Z]*|*[A-Z]*[A-Z]*[A-Z]*)
修改
感到困惑。首先,我只允许使用元字符,没有正则表达式,没有测试,没有像awk / sed /其他的工具。 而且,大写字母不能是连续的。
修改
好的,这个似乎有用(但更长!)。
export LC_COLLATE=C
ls @(!(*[A-Z]*)|!(*[A-Z]*)[A-Z]!(*[A-Z]*)|[A-Z]!(*[A-Z]*)[A-Z]!(*[A-Z]*)|!(*[A-Z]*)[A-Z]!(*[A-Z]*)[A-Z]!(*[A-Z]*)[A-Z]!(*[A-Z]*)
答案 0 :(得分:3)
你的模式对我不起作用。一个问题是,在许多非C语言环境中,[A-Z]
包含一些小写字符。
$ for c in a A b B z Z; do if [[ $c = [A-Z] ]]; then echo "match: $c"; else echo "no match: $c"; fi; done
no match: a
match: A
match: b
match: B
match: z
match: Z
使用LANG=C
再试一次。如果您想要匹配大写字符而不考虑区域设置,请使用[[:upper:]]
。
你的另一个原因是它的部分内容始终匹配。
例如:
!(*[A-Z]*)
(即使使用[[:upper:]]
进行了更正)匹配(拒绝)任何仅包含大写字符的内容,无论长度如何。但是,(部分更正的)模式的其余部分显式包含大写字符,而由于星号而隐含地包含任何字符,包括大写字符。所以只是第一部分:
*[[:upper:]]*
表示要包含至少包含一个大写字符而不考虑的所有字符串,以及可能存在的字符数:一,十,百万。
相反,试试这个:
if [[ $string != *[[:upper:]]*[[:upper:]]*[[:upper:]]*[[:upper:]]* ]]
then
echo "match: fewer than four uppercase character"
fi
它只是检查是否有四个或更多大写字符。
您还可以使用正则表达式(在Bash 3.2或更高版本中):
if [[ ! $string =~ ^.*[[:upper:]].*[[:upper:]].*[[:upper:]].*[[:upper:]].*$ ]]
then
echo "match: fewer than four uppercase character"
fi
另一种方法是删除所有非大写字符并比较长度差异。
演示:
#!/bin/bash
strings[1]='AbCdEfghi'
strings[2]='ABCD'
strings[3]='Ab1Cd2Ef3ghi'
strings[4]='A1BbC2Dd'
for string in "${strings[@]}"
do
test=${string//[^[:upper:]]}
if (( ${#test} > 3 ))
then
echo "no match: $string"
else
echo "match: $string"
fi
done
答案 1 :(得分:0)
尝试:
ls | grep -E '^([^A-Z]*[A-Z][^A-Z]*){0,3}$'
答案 2 :(得分:0)
$ echo "BCDAdf" | awk '{m=gsub(/[A-Z]/,"");print (m<4) ?"match":"no match"}'
no match
$ echo "CDAdf" | awk '{m=gsub(/[A-Z]/,"");print (m<4) ?"match":"no match"}'
match
答案 3 :(得分:0)
Erik提到使用grep
,所以我也会使用它。
我认为应该是:
/bin/ls -1 | grep -E '^[^A-Z]*([A-Z][^A-Z]*([A-Z][^A-Z]*([A-Z][^A-Z]*)?)?)?$'
可以缩短为:
/bin/ls -1 | grep -E '^[^A-Z]*([A-Z][^A-Z]*){0,3}$'
如果您真的想使用bash
扩展模式,它应该如下所示:
/bin/ls -1 *([^A-Z])?([A-Z]*([^A-Z]))?([A-Z]*([^A-Z]))?([A-Z]*([^A-Z]))
请注意,您必须设置LC_COLLATE=C
才能生效。
如果你想把它写得更短,你可以使用参数扩展(即变量扩展)在文件名扩展之前发生的事实,并做一些奇怪的事情:
u='[A-Z]' # $u == uppercase characters
U='[^A-Z]' # $U == non-uppercase characters
/bin/ls -1 *($U)?($u*($U))?($u*($U))?($u*($U))
这是不是一个好主意,我留给你决定。 ; - )
答案 4 :(得分:0)
我相信这样的事情是正确的:
!(*([^[:upper:]])[[:upper:]]*([^[:upper:]])[[:upper:]]*([^[:upper:]])[[:upper:]]*([^[:upper:]])[[:upper:]]*)
当然还有extglob。