在 AIX 中使用单个 awk 从字段中提取子字符串

Extract substring from a field with single awk in AIX

我有一个文件 file,其内容如下:

stringa    8.0.1.2     stringx
stringb    12.01.0.0    stringx

我必须从字段 2 中获取一个子字符串(前两个带点的值)。
我目前正在做 cat file | awk '{print }' | awk -F. '{print "."}' 并获得预期的输出:

8.0
12.01

查询是如何用单个 awk 做到这一点?
我试过 match() 但没有看到反向引用的选项。 任何帮助将不胜感激。

你可以这样做。

$ awk '{ split(,str,"."); print str[1]"."str[2] }' file
8.0
12.01

此外,请记住您的 cat 不是必需的。直接把文件给awk.

我会使用 GNU AWKsplit 函数如下,令 file.txt 内容为

stringa    8.0.1.2     stringx
stringb    12.01.0.0    stringx

然后

awk '{split(,arr,".");print arr[1]"."arr[2]}' file.txt

输出

8.0
12.01

解释:在 . 第二个字段拆分并将元素放入数组 arr.

(在 gawk 4.2.1 中测试)

您可以匹配 digits 。来自第二列的 digits 并打印是否匹配:

awk 'match(, /^[[:digit:]]+\.[[:digit:]]+/) {
    print substr(, RSTART, RLENGTH)
}
' file

输出

8.0
12.01

使用 GNU grep 请尝试执行以下命令一次。

grep -oP '^\S+\s+\K[[:digit:]]+\.[[:digit:]]+' Input_file

说明: 这里使用 GNU grep。使用其 -oP 选项打印匹配的部分并在此处使用 -P 选项启用 PCRE。在主程序中,从非 space 字符开始匹配,后跟 1 个或多个 spaces,然后使用 \K 选项忘记该匹配。然后匹配 1 个或多个数字出现后跟一个点;随后是数字。如果找到匹配项,则打印匹配值。

还有 GNU awkgensub():

awk '{print gensub(/([[:digit:]]+[.][[:digit:]]+)(.*)/,"\1","g",)}' 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