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

Linux 使用shell脚本从字符串中提取信息,linux,bash,shell,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 主要问题是信息的顺序不同,有些信息在每行中都

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

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_interest()
将打印行的四个有趣部分,用
符号分隔:

extract_interesting "$s" "$pattern"
将打印

Attribute#foo_1#2015-07-24 05:12:12.123#1555
Attribute
foo_1
2015-07-24 05:12:12.123
1555
要将其读入单独的shell变量,请使用以下模式:

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

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

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

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_interest()
将打印行的四个有趣部分,用
符号分隔:

extract_interesting "$s" "$pattern"
将打印

Attribute#foo_1#2015-07-24 05:12:12.123#1555
Attribute
foo_1
2015-07-24 05:12:12.123
1555
要将其读入单独的shell变量,请使用以下模式:

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

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

使用
grep
Perl
regex的示例:

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

使用
grep
Perl
regex的示例:

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

下面是一个简单的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
awk-F'\t''开始{F=split(“属性|日期|时间戳|数量”,k,/\\\\\/)}

{n=split($2,a,/\\|/);for(i=1;i这里是一个简单的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
awk-F'\t''开始{F=split(“属性|日期|时间戳|数量”,k,/\\\\\/)}

{n=split($2,a,/\\\\\/);用于(i=1;输入中没有
Date
timeStamp
。如果您想得到具体的解决方案,请使用更好的示例输入和预期输出。我认为日期和时间戳是从
SendingTime
字段中提取的。输入中没有
Date
timeStamp
。如果您想得到具体结果,请对于解决方案,请使用更好的示例输入和预期输出。我认为日期和时间戳是从
SendingTime
字段中提取的。我将使用
bash
正则表达式匹配替换所有到
sed
[[$input=~$pattern]]
,然后从
BASH_REMATCH
中提取4个值。你是对的。相同的方法,不同的方法。我在这里使用
sed
有点过时。在每一行上分叉一个新的进程会带来大量开销。Op说信息可能以不同的顺序出现,即
SendingTime=2015-07-24 05:12:12.123 | S-Id=9999 |…@str:Attribute |…
可能是一个有效的行。然后的方法仍然是一样的。您只需对每一行进行多次处理,可能对每个感兴趣的值都要处理一次。使用上述技术,一次一次从行中获取每个感兴趣的信息。我将用
bash
正则表达式mat替换所有to
sed
ch.
[[$input=~$pattern]]
,然后从
BASH_REMATCH
中提取4个值。你是对的。相同的方法,不同的方法。我在这里使用
sed
有点过时。在每一行上分叉一个新的进程会带来大量开销。Op说信息可能以不同的顺序出现,即
SendingTime=2015-07-24 05:12:12.123 | S-Id=9999 |…@str:Attribute |…
可能是一个有效的行。当时的方法仍然是一样的。你只需要对每一行进行多次处理,可能对每一个有趣的值处理一次。使用上面描述的技术,一次从行中获取每一个有趣的信息。非常有帮助!这是我最终使用的版本,非常感谢帮助!这是我最后使用的版本,谢谢