Regex Bash计算字符串中的字母,输出总是有点不同
我的剧本有点问题。 我的程序从用户那里接收一个字符串,并将其加在一起,形成循环中的一个大字符串,只有用户在代码中的某个地方键入星号(Regex Bash计算字符串中的字母,输出总是有点不同,regex,bash,shell,grep,wc,Regex,Bash,Shell,Grep,Wc,我的剧本有点问题。 我的程序从用户那里接收一个字符串,并将其加在一起,形成循环中的一个大字符串,只有用户在代码中的某个地方键入星号(*)时,循环才会结束。随后,该代码分别计算字母、数字和非字母数字字符。它使用了grep[0-9]| wc的组合。然而输出总是有点疯狂,我给出了几个字符串示例 *=0数字7字母0特殊 a1=2个数字2个字母=0个特殊字母 abc123*=4个数字4个字母0个特殊字符 abc123…*=4个数字4个字母4个特殊字符 ....******=0数字=字母6特殊 换句话说
*
)时,循环才会结束。随后,该代码分别计算字母、数字和非字母数字字符。它使用了grep[0-9]| wc
的组合。然而输出总是有点疯狂,我给出了几个字符串示例
=0数字7字母0特殊*
=2个数字2个字母=0个特殊字母a1
=4个数字4个字母0个特殊字符abc123*
=4个数字4个字母4个特殊字符abc123…*
=0数字=字母6特殊....******
echo $completestring | grep -o "[0-9]*" | wc -c
echo $completestring | grep -o "[a-zA-Z]*" | wc -c
echo $completestring | grep -o "[,._+:@%/-]*" | wc -c
$completestring contains a string written by the user
星号
星号(*
)与前面的字符或组匹配零次或多次。因此
匹配任何内容,即数字零次或多次李>[0-9]*
匹配任何字符,即零次或多次匹配范围内的字符[a-zA-Z]*
*
表达式,例如:
李>[0-9].*
[a-zA-Z].*
)与单个字符匹配
一些测试:
$ echo 'test' | grep '[0-9].*'; echo $?
1
$ echo 'test' | grep '[0-9]*'; echo $?
test
0
如果选择了行,则退出状态($?
)为0,如果未选择行,则为1
引用
另外请注意,如果要防止重新解释特殊字符:“$myvar”
,则应将shell变量括在双引号中
计算模式匹配的数量
Grep的-o
选项只打印匹配行中匹配的非空部分,每个部分都在单独的行中。因此,匹配部分的计数等于输出中的行数。因此您需要wc-l
:
$ echo 'abc123' | grep -o '[a-z]' | wc -l
3
$ echo 'abc123def' | grep -o '[a-z]\+'
abc
def
如果要计算特定类型字符的实例数,可以执行以下操作:
echo $completestring | grep -o "[0-9]" | wc -l
echo $completestring | grep -o "[a-zA-Z]" | wc -l
echo $completestring | grep -o "[,._+:@%/-]" | wc -l
例如,这将为给定的完整字符串提供以下输出:
completestring=”foo@a321abcdr%20:/mango/25b“
grep匹配:3
2
1
2
0
2
5
echo $completestring | grep -o "[a-zA-Z]" | wc -l
15
grep匹配:f
o
o
a
a
b
c
d
r
m
a
n
g
o
b
echo $completestring | grep -o "[,._+:@%/-]" | wc -l
5
grep匹配:@
%
:
/
/
如果要将数字和单词的簇作为单个实例进行计数(例如,mango应为1而不是5,321应为1而不是3),则可以使用以下方法:
echo $completestring | grep -o "[0-9][0-9]*" | wc -l
echo $completestring | grep -o "[a-zA-Z][a-zA-Z]*" | wc -l
我认为特殊字符数是以每个字符为基础的。你的想法有几个问题 首先,请,请,无论如何:引用您的变量展开式
$ completestring=.* ; echo $completestring
. .. .directory .#screenon
相反,我相信你想要:
$completestring=.*;回显“$completestring”
*$ echo "123" | wc -c
4
您需要使用echo-n
(不可移植,不推荐)或printf“%s”
$ printf '%s' "123" | wc -c
3
$ completestring="jkfdsnlal92845t02u74ijopzidjb jd"
$ echo $completestring | grep -o [0-9]*
92845
02
74
没有简单的计算方法。一种简化方法是仅使用范围:
$ echo $completestring | grep -o [0-9]
9
2
8
4
5
0
2
7
4
然后你可以数行:
$ echo $completestring | grep -o [0-9] | wc -l
9
注意:从这里开始,我将只使用一个as变量。更容易输入,希望您理解:)
*
。根据您读取变量的方式,您可以使用Ctrl-D向系统发送一个EOF
信号,以结束从用户处读取输入$ a="jkfdsnlal92845t02u74ijopzidjb jd"
$ b="${#a//[^0-9]}" # remove all characters
# that are not decimal digits
$ echo "${b}" # Not really needed, but this
928450274 # what var b contains.
$ echo "${#b}" # Print the length of var b.
9
您在代码中编写的内容可以翻译成这样(需要将/
引用为\/
,我将*
包含在特殊列表中)
将打印
Digits=3 Alpha=3 Special=1
立法会
但是,此系统存在问题。它还将计算许多UNICODE字符:
$ c=aßbéc123*; a=${c//[^a-zA-Z]}; echo "string=$a count=${#a}"
string=aßbéc count=5
我相信这就是你需要的
但如果必须限制为128个ascii字符,则在执行范围选择时,将LC_ALL或更具体地说,LC_COLLATE更改为C语言环境:
$ (LCcompletestring=abc123*; alpha=${completestring//[^a-zA-Z]}; alpha=${#alpha}; echo "${alpha}"_COLLATE=C a=${c//[^a-zA-Z]}; echo "string=$a count=${#a}")
string=abc count=3
(…)是使用子shell,避免在整个shell中设置LC\U COLLATE。但是,您可以在脚本开始时设置它,它也可以工作 对不起,时间太长了。但不管怎样,我还是错过了什么吗
嗯,是的,我希望您的密码不会包含控制字符(C0:ASCII从1到31和127,以及C1:128到159)。因为数一数有几处曲折。可能超出了这个答案。你想让它说a1=1个字母1个数字和0个特殊数字吗?额外的计数与正在计数的新行有关,因为你在
-c
中使用-wc
,如果你匹配[0-9]*
匹配”
我想你的回答不会回答这个问题question@AhmedMasud为什么?我可能弄错了,但是你的解决方案会显示grep是否在字符串中找到某个内容。我尝试数一数,例如:如果我有字符串“aabbcc123123…”,那么我希望我的代码是:6个字母,6个数字,5个特殊字符(包括aster)
completestring=abc123*
dig=${completestring//[^0-9]}; dig=${#dig}
alpha=${completestring//[^a-zA-Z]}; alpha=${#alpha}
special=${completestring//[^,._+:@%\/*-]}; special=${#special}
echo "Digits=$dig Alpha=$alpha Special=$special"
Digits=3 Alpha=3 Special=1
$ c=aßbéc123*; a=${c//[^a-zA-Z]}; echo "string=$a count=${#a}"
string=aßbéc count=5
$ (LCcompletestring=abc123*; alpha=${completestring//[^a-zA-Z]}; alpha=${#alpha}; echo "${alpha}"_COLLATE=C a=${c//[^a-zA-Z]}; echo "string=$a count=${#a}")
string=abc count=3