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

时间:2015-07-02 11:36:07

标签: linux bash shell

我有一个文本文件,其中包含以下格式的行:

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

主要问题是信息的顺序不同,有些信息的每行都有更多/更少的不需要的数据。因此拆分成阵列就不会削减它。

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

grep带有Perl正则表达式的示例:

#!/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

答案 2 :(得分:0)

这是一个简单的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