我有一个从文件中读取的字符串,它包含所有类型的非ascii字符,如下所示
line=^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå
现在我只需要提取&#39; 15552655&#39;这个数字。
我尝试了什么:
line=$(sed -n '1p' < file)
number=$(echo "${line//[!0-9]/}")
or
number=$(echo $line | sed 's/[^0-9]*//g')
但这会返回&#39; 155526554&#39;,所以我需要一种方法从连续包含至少4个连续数字的行中提取子字符串[保证该模式中至少有4个数字]
非常感谢任何帮助。
更新-1:
number=$(echo $line | sed 's/[^0-9]*\([0-9]\{1,\}\).*$/\1/')
这似乎适用于上述情况,但如果输入采用此格式
,则会失败line=^AÀÀ^P^4G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå
在这种情况下,它返回4,即它返回第一轮数字。我需要添加一些说给我最长或超过4个数字的东西。
答案 0 :(得分:1)
这个怎么样:
number=$(echo "$line" | tr -cs '0-9' '\n' | awk '{if (length>l) { n=$0; l=length }} END { print n }')
说明:如果字符串包含某些shell元字符,$line
周围的双引号会阻止shell执行任何奇怪的操作。 tr -cs '0-9' '\n'
用换行符替换不是数字的所有内容,“替换”替换字符的运行;这实际上产生了文件中的数字列表,每行一个。然后在awk中,{if (length>l) { n=$0; l=length }}
表示对于每个输入行,如果其length
比之前看到的l
长(n
),请将l
设置为当前行, END { print n }
到它的长度。 {{1}}部分使其在输入结束时打印最长的行。
答案 1 :(得分:0)
我的建议是,你将这行划分为以逗号分隔的数字,然后根据你的内心检查这些数字:
line="^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå"
number=$(echo $line | sed -E 's/[^0-9]+/,/g')
echo $number
==> ,15552655,84,8,
找到最长的是复杂的。这是一个解决方案,但Gordon Davisson的解决方案是单线解决方案。
#!/bin/bash
line="^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå"
number=$(echo $line | sed -E 's/[^0-9]+/\\n/g')
max_length=0
this_index=0
saved_index=-1
echo $number |
{ while read num ; do
pieces[$this_index]=$num
this_length=$(echo $num | wc -c | sed 's/ //g')
if [ $this_length -gt $max_length ] ; then
max_length=$this_length
saved_index=$this_index
fi
this_index=$(expr $this_index + 1)
done
echo maxnum is ${pieces[$saved_index]}
}