我有一个文件,
file
,内容如下:
stringa 8.0.1.2 stringx
stringb 12.01.0.0 stringx
我必须从字段 2 中获取一个子字符串(前两个带点的值)。 我目前正在做
cat file | awk '{print $2}' | awk -F. '{print $1"."$2}'
并得到预期的输出:
8.0
12.01
如何使用单个 AWK 来完成此操作?
我尝试过使用 match(),但我没有看到向后引用的选项。
你可以做这样的事情。
awk '{ split($2,str,"."); print
输出:
str[1]"."str[2] }' file
8.0
12.01
另外,请记住,不需要您的
cat
。只需将文件直接交给awk
即可。
使用 GNU
grep
请尝试执行以下命令一次。
grep -oP '^\S+\s+\K[[:digit:]]+\.[[:digit:]]+' Input_file
说明:此处使用GNU
grep
。使用其 -oP
选项打印匹配的部分,并在此处使用 -P
选项启用 PCRE。在主程序中,从起始非空格字符开始匹配,后跟 1 个或多个空格,然后使用 \K
选项忘记该匹配。然后匹配 1 个或多个数字出现,后跟一个点;接下来是数字。如果找到匹配项,则会打印匹配的值。
我会使用GNU
AWK
的split
函数如下,让file.txt内容为
stringa 8.0.1.2 stringx
stringb 12.01.0.0 stringx
然后
awk '{split($2,arr,".");print arr[1]"."arr[2]}' file.txt
输出
8.0
12.01
解释:在
.
第二个字段处拆分并将元素放入数组arr
。
(在 gawk 4.2.1 中测试)
您可以匹配数字。第二列中的数字,如果有匹配则打印:
awk 'match($2, /^[[:digit:]]+\.[[:digit:]]+/) {
print substr($2, RSTART, RLENGTH)
}
' file
输出
8.0
12.01
还有 GNU
awk
和 gensub()
:
awk '{print gensub(/([[:digit:]]+[.][[:digit:]]+)(.*)/,"\\1","g",$2)}' file
8.0
12.01
gensub()
提供了在替换文本中指定正则表达式组件的功能,使用正则表达式中的括号来标记组件,然后在替换文本中指定 \\n
,其中 n
是从 1 到 9 的数字。您也许根本不应该使用 awk(或任何其他外部程序),而应该依赖 shell 的字段分割功能和一些变量扩展。例如:
# printf "%s\n%s\n" "stringa 8.0.1.2 stringx" \
"stringb 12.01.0.0 stringx" |\
while read first second third junk ; do
printf "=%s= =%s= =%s=\n" "$first" "$second" "$third"
done
=stringa= =8.0.1.2= =stringx=
=stringb= =12.01.0.0= =stringx=
正如您所看到的,该值已经被捕获在变量“$second”中,您只需要进一步隔离您想要查看的部分 - 第一个和第二个部分用点分隔。您可以通过参数扩展来做到这一点:
# variable="8.0.1.2"
# echo ${variable%.*.*}
8.0
或者像这样:
# variable="12.01.0.0"
# echo ${variable%${variable#*.*.}}
12.01
或者您可以使用进一步的读取语句来分离各个部分,然后将它们重新组合在一起:
# variable="12.01.0.0"
# echo ${variable} | IFS=. read parta partb junk
# echo ${parta}.${partb}
12.01
所以,把所有的放在一起:
# printf "%s\n%s\n" "stringa 8.0.1.2 stringx" \
"stringb 12.01.0.0 stringx" |\
while read first second third junk ; do
printf "%s\n" "$second" | IFS=. read parta partb junk
printf "%s.%s\n" "$parta" "$partb"
done
8.0
12.01