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替换所有tosed
ch.[[$input=~$pattern]]
,然后从BASH_REMATCH
中提取4个值。你是对的。相同的方法,不同的方法。我在这里使用sed
有点过时。在每一行上分叉一个新的进程会带来大量开销。Op说信息可能以不同的顺序出现,即SendingTime=2015-07-24 05:12:12.123 | S-Id=9999 |…@str:Attribute |…
可能是一个有效的行。当时的方法仍然是一样的。你只需要对每一行进行多次处理,可能对每一个有趣的值处理一次。使用上面描述的技术,一次从行中获取每一个有趣的信息。非常有帮助!这是我最终使用的版本,非常感谢帮助!这是我最后使用的版本,谢谢