我有一个bash变量,其值如下:
10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
价值内没有空格。该值可以很长或很短。这里存在诸如65:3.0
之类的对。我知道对的第一部分中的数字的值,比如65
。我想提取数字3.0
或对65:3.0
。我不知道65
的位置(偏移)。
我将非常感谢能够进行此类提取的bash脚本。感谢。
答案 0 :(得分:5)
可能awk是最直接的方法:
awk -F: -v RS=',' '$1==65{print $2}' <<< "$var"
3.0
或者得到这对:
$ awk -F: -v RS=',' '$1==65' <<< "$var"
65:3.0
答案 1 :(得分:4)
这是一个纯粹的Bash解决方案:
var=10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
while read -r -d, i; do
[[ $i = 65:* ]] || continue
echo "$i"
done <<< "$var,"
如果break
中只有一个echo "$i"
,或者您只想要第一个65:...
,则可以在var
之后使用3.0
。
获取值echo "${i#*:}"
:65
。
其他(纯Bash)方法,无需显式解析字符串。我假设您只是在字符串中查找第一个var=10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
value=${var#*,65:}
value=${value%%,*}
echo "$value"
,并且它出现在字符串中:
65
对于长字符串,这将非常慢!
与上面相同,但会输出与var=10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
tmpvar=,$var
while [[ $tmpvar = *,65:* ]]; do
tmpvar=${tmpvar#*,65:}
echo "${tmpvar%%,*}"
done
对应的所有值(如果没有,则输出无):
var=10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
IFS=, read -ra ary <<< "$var"
for i in "${ary[@]}"; do
[[ $i = 65:* ]] || continue
echo "$i"
done
同样的事情,对于长串来说这会很慢!
我在纯Bash中获得的最快速度是我原来的答案(并且10000个字段很好):
var=10:3.0,16:4.0,32:4.0,39:2.0,65:3.0,95:4.0,110:4.0,111:4.0,2312:1.0
[[ ,$var, =~ ,65:([^,]+), ]] && echo "${BASH_REMATCH[1]}"
事实上,不,我在纯Bash中获得的最快速度就是这个正则表达式:
awk
测试此vs 65:3.0
,
printf -v var '%s:3.0,' {100..11000}
var+=65:42.0
time awk -F: -v RS=',' '$1==65{print $2}' <<< "$var"
在最后的位置:
time { [[ ,$var, =~ ,65:([^,]+), ]] && echo "${BASH_REMATCH[1]}"; }
显示0m0.020s(粗略平均值),而:
65:3.0
显示0m0.008s(粗略平均值)。
printf -v var '%s:3.0,' {1..10000}
time awk -F: -v RS=',' '$1==65{print $2}' <<< "$var"
不在最后:
time awk -F: -v RS=',' '$1==65{print $2;exit}' <<< "$var"
显示0m0.020s(粗略平均值)并提前退出:
time { [[ ,$var, =~ ,65:([^,]+), ]] && echo "${BASH_REMATCH[1]}"; }
显示0m0.010s(粗略平均值),而:
{{1}}
显示0m0.002s(粗略平均值)。
答案 2 :(得分:3)
试
echo $var | tr , '\n' | awk '/65/'
,其中
tr , '\n'
将逗号变为新行awk '/65/'
选择65 或
echo $var | tr , '\n' | awk -F: '$1 == 65 {print $2}'
,其中
-F:
使用:作为分隔符$1 == 65
选择65行作为第一个字段{ print $2}
打印第二个字段答案 3 :(得分:3)
这是gnu awk
awk -vRS="(^|,)65:" -F, 'NR>1{print $1}' <<< "$var"
3.0
答案 4 :(得分:3)
使用grep:
grep -o '\b65\b[^,]*' <<<"$var"
65:3.0
或
grep -oP '\b65\b:\K[^,]*' <<<"$var"
3.0
\K
选项忽略匹配模式之前的所有内容并忽略模式本身。它是-P
命令的Perl兼容性(grep
)。
答案 5 :(得分:2)
使用sed
sed -e 's/^.*,\(65:[0-9.]*\),.*$/\1/' <<<",$var,"
<强>输出:强>
65:3.0
有两种不同的方法可以防止{{1>}成为第一行或最后一行。无论如何,添加65:3.0
以包围变量以提供发生。下面,Gnu扩展名commas
用于指定零或一个出现次数。
\?
无论字符串中出现何处,都处理sed -e 's/^.*,\?\(65:[0-9.]*\),\?.*$/\1/' <<<$var
。
答案 6 :(得分:1)
尝试egrep如下:
echo $myvar | egrep -o '\b65:[0-9]+.[0-9]+' |