缩短awk命令管道

时间:2019-03-22 04:51:55

标签: linux awk

在shell上使用linux很新。

我想减少用于提取以下数据的管道数量。

V       190917135635Z           1005    unknown /C=DE/ST=City/L=City/O=something/OU=Somewhat/CN=someserver.com/emailAddress=test@toast.com

我的目标是将以下值放在单独的文件中

190917135635 someserver.com

我现在使用的命令相当长,已通过管道传递,看起来像这样

grep -v '^R' $file | awk '{print $2, $6}' | awk -F'[=|/]' '{print $1, $3}' | awk '{print $1, $3}' |  awk -F 'Z ' '{print $1, $2}' > sdata.txt

(文件包含以'R'开头的其他行,因此我排除了我的grep中的行)

这是合法的方式吗?

有没有办法在较短的命令中得到这个?

非常感谢!

6 个答案:

答案 0 :(得分:1)

看起来您的某些数据字段用于创建SSL证书,因此许多字段可能包含SPACES,即城市,组织名称等。这就是为什么您需要许多awk行(???)的原因。这是一种可以帮助您克服这些问题的方法。因此,目标不是通过转换现有的代码逻辑,而是通过搜索子字符串CN=并获取其对应的值来查找域名。

awk  '
    !/^R/{
        start  = index($0, "CN=")+3
        end    = index(substr($0, start), "/")
        domain = end ? substr($0, start, end-1) : substr($0, start)
        print $2, domain
    }
' file.txt

位置:

  • 我们使用index()查找子字符串CN=的起始位置,+3将是域名的起始点
  • 然后搜索下一个/,以获取该域的末尾位置。如果在行尾,则不会有/,因此end将为'0'
  • 然后,使用CN=获得子字符串substr($0, start, end-1)与下一个'/'之间的域名,或者使用substr($0, start)获得行尾。

简短版本:

awk '!/^R/{s=index($0, "CN=")+3; e=index(substr($0, s), "/"); print $2, substr($0, s, e ? e-1 : 253)}' file.txt

其中253是可能的最长域名,可能足以满足您的需求。

更新

实际上,使用match()会容易得多,但要点是相同的:

awk '!/^R/{if(match($0, "/CN=([^/]*)")) print $2, substr($0, RSTART+4, RLENGTH-4)}' file.txt

答案 1 :(得分:1)

另一个awk。使用match查找CN条目,并使用substr提取CN条目以供print打印(如果存在)。

$ awk '!/^R/{
    print $2,
        (match($0,/CN=[^/]+/)?substr($0,RSTART+3,RLENGTH-3):"")  # 3==length("CN=")
}' file

输出:

190917135635Z someserver.com

答案 2 :(得分:1)

如果这样:

$ awk -F'[[:space:]/=]+' '!/^R/{print $2+0, $16}' file
190917135635 someserver.com

不是您所需要的,然后更新您的问题以阐明您的要求并提供更真实的示例输入/输出。

答案 3 :(得分:0)

编辑: :严格考虑OP的Input_file与所示示例相同。看到OP的样本后,可以尝试跟随。

awk -F"[ =/Z]" '!/^R/{print $8,$37}'  Input_file


对于FUN :),如果有人想尝试OP的方法,那么我们可以尝试遵循。

awk '
!/^R/{
  val=$2 OFS $5
  split(val,array,"[ /Z]")
  val1=array[1] OFS array[9] OFS array[10]
  split(val1,array1,"[ =]")
  print array1[1],array1[3]
}
'  Input_file

答案 4 :(得分:0)

使用GNU sed

sed -E -n '/^R/d; s/^[A-Za-z]\s+([0-9]+)\s+[0-9]+\s+.*\/CN=(.*)\/.*/\1 \2/p' input_file > new_file

答案 5 :(得分:0)

您在第二个$6命令中使用awk,这意味着与示例数据不同,您的 5th 列内部可能有空间 s 如图所示,它也正在提取CN=部分(CNAME?)。

因此,这是一种更兼容且更精确的sed方式,它不需要GNU sed:

sed -n -e '/^R/!{' -e 's|^[^[:space:]]*[[:space:]]*\([^[:space:]Z][^[:space:]Z]*\).*/CN=\([^/][^/]*\).*|\1 \2|p;}'

如果您只想在第二栏中输入数字,并且以数字开头,那么您可以更改为使用该数字:

sed -n -e '/^R/!{' -e 's|^[^[:space:]]*[[:space:]]*\([0-9][0-9]*\).*/CN=\([^/][^/]*\).*|\1 \2|p;}'