繁体   English   中英

使用Shell脚本从字符串中提取信息

[英]Extracting information from string using shell script

我有一个文本文件,其行格式如下:

9999.0      @str:Attribute|ID=foo_1|SendingTime=2015-07-24 05:12:12.123|S-Id=9999|IDSource=Test_3|Qty=1555

由此,我想使用shell脚本从每一行中获取各个部分。 例如说:

VAR1 = Attribute,
VAR2 = Date,
VAR3 = timeStamp,
VAR4 = Qty

主要问题是信息以不同的顺序出现,有些信息每行中包含更多/更少的不需要的数据。 因此,拆分为一个数组不会削减它。

解析复杂行的一种通用方法是使用正则表达式来描述它们,然后使用括号指出哪些部分是有趣的:

s='9999.0      @str:Attribute|ID=foo_1|SendingTime=2015-07-24 05:12:12.123|S-Id=9999|IDSource=Test_3|Qty=1555'
pattern='.*@str:\([^|]*\).*ID=\([^|]*\).*SendingTime=\([^|]*\).*Qty=\([^|]*\).*$'
extract_interesting() {
  input=$1
  pattern=$2
  echo "$input" | sed s/"$pattern"/'\1#\2#\3#\4'/
}

函数extract_interesting()将打印该行的四个有趣部分,以#符号分隔:

extract_interesting "$s" "$pattern"

将打印

Attribute#foo_1#2015-07-24 05:12:12.123#1555

要将其读入单独的shell变量,请使用以下模式:

IFS=# read a b c d < <(extract_interesting "$s" "$pattern")

然后

echo "$a"; echo "$b"; echo "$c"; echo "$d"

将打印

Attribute
foo_1
2015-07-24 05:12:12.123
1555

Perl正则表达式的grep示例:

#!/bin/bash
s="9999.0      @str:Attribute|ID=foo_1|SendingTime=2015-07-24 05:12:12.123|S-Id=9999|IDSource=Test_3|Qty=1555"
var1="$(echo "$s" |grep -oP "(?<=@str:)[^|]*")"        # @str:
var2="$(echo "$s" |grep -oP "(?<=SendingTime=)[^|]*")" # SendingTime=
var3="${var2#* }"                                      # Date
var2="${var2% *}"                                      # timestamp
var4="$(echo "$s" |grep -oP "(?<=Qty=)[^|]*")"         # Qty
echo "$var1 | $var2 | $var3 | $var4"

输出:

Attribute | 2015-07-24 | 05:12:12.123 | 1555

这是一个简单的Awk脚本,它提取字段并按指定顺序打印它们。

awk -F '\t' 'BEGIN { f = split("Attribute|Date|timeStamp|Qty", k, /\|/) }
    { n = split($2, a, /\|/); for (i=1; i<=n; ++i) {
        if (a[i] ~ /^@str:/) v["Attribute"] = substr(a[i], 6);
        else if (a[i] ~ /^SendingTime=/) {
            v["Date"] = substr(a[i], 13, 10); v["timeStamp"] = substr(a[i], 24)
        } else if (a[i] ~ /^Qty=/) v["Qty"] = substr(a[i], 5);
    }
    for (s=1; s<=f; s++) printf("%s=%s\n", k[s], v[k[s]]);
    delete v }' inputfile

BEGIN块按我们想要的顺序设置了要收集和打印的字段标签的数组k 最后的for循环遍历此数组。 主要的复杂性是在中间的块中,在该块中,我们进一步拆分了| 分隔符并遍历结果; 我们要提取的每个字段都是根据其在匹配中的偏移量填充的。

没有检查是否缺少字段,并且有很多关于输入(制表符分隔,是吗?)和输出格式的假设,因为您的问题不是很清楚。

在线演示: http : //ideone.com/2yvz2X

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM