Linux sed在每行重复字符串
我有一个包含数百行的文件Linux sed在每行重复字符串,linux,bash,shell,sed,grep,Linux,Bash,Shell,Sed,Grep,我有一个包含数百行的文件inventory.txt。它列出了与客户ID/名称、库存ID/名称和产品ID/名称相关的数据。文件的常规设置,在任何给定行上都可能出现acustomerId=123。在这一行之后,将出现一个inventoryId=abc行。此文件的外观如下所示: <> START OF FILE Customer ID=9000, Customer Name=Acme, Inc Inventory ID=INV_ID1, Inventory Name=Acme_INV1 P
inventory.txt
。它列出了与客户ID/名称、库存ID/名称和产品ID/名称相关的数据。文件的常规设置,在任何给定行上都可能出现acustomerId=123
。在这一行之后,将出现一个inventoryId=abc
行。此文件的外观如下所示:
<> START OF FILE
Customer ID=9000, Customer Name=Acme, Inc
Inventory ID=INV_ID1, Inventory Name=Acme_INV1
Product ID=100, Product Name=Banana
Product ID=200, Product Name=Apple
Inventory ID=INV_ID2, Inventory Name=Acme_INV2
Product ID=100, Product Name=Banana
Product ID=300, Product Name=Kiwi
Customer ID=7500, Customer Name=Anvil, Corp
Inventory ID=INV_ID3, Inventory Name=Anvil_INV1
Product ID=200, Product Name=Apple
<> END OF FILE
我知道如何使用SED将输入数据格式化为带有逗号和引号的CSV文件输出,但我很难弄清楚如何强制客户ID
和客户名称
在每个库存ID
和库存名称
行的开头重复
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);
my ($customer, $name);
while (<>) {
if (/Customer ID=(.*), Customer Name=(.*)/) {
($customer, $name) = ($1, $2);
} elsif (/Inventory ID=(.*), Inventory Name=(.*)/) {
say join ', ' => map qq("$_"), $customer, $name, $1, $2;
}
}
sed -n '/^Customer ID/ h; /^Inventory ID/ { G; s/.*=\([^,]*\).*=\([^\n]*\).*=\([^,]*\).*=\(.*\)/"\3", "\4", "\1", "\2"/; p }' inventory.txt
#/usr/bin/perl
使用警告;
严格使用;
使用特征qw(例如);
我的($customer,$name);
而(){
如果(/Customer ID=(.*),则客户名称=(.*)/){
($customer,$name)=($1,$2);
}elsif(/Inventory ID=(*),Inventory Name=(.*)/){
说加入“,”=>MapQQ($),$customer,$name,$1,$2;
}
}
Perl解决方案:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);
my ($customer, $name);
while (<>) {
if (/Customer ID=(.*), Customer Name=(.*)/) {
($customer, $name) = ($1, $2);
} elsif (/Inventory ID=(.*), Inventory Name=(.*)/) {
say join ', ' => map qq("$_"), $customer, $name, $1, $2;
}
}
sed -n '/^Customer ID/ h; /^Inventory ID/ { G; s/.*=\([^,]*\).*=\([^\n]*\).*=\([^,]*\).*=\(.*\)/"\3", "\4", "\1", "\2"/; p }' inventory.txt
#/usr/bin/perl
使用警告;
严格使用;
使用特征qw(例如);
我的($customer,$name);
而(){
如果(/Customer ID=(.*),则客户名称=(.*)/){
($customer,$name)=($1,$2);
}elsif(/Inventory ID=(*),Inventory Name=(.*)/){
说加入“,”=>MapQQ($),$customer,$name,$1,$2;
}
}
这里有一种方法可以使用awk
:
awk -F= '{ sub(/,.*/,"",$2) } /^Customer ID/ { r = $2 OFS $3 } /^Inventory ID/ { print "\"" r, $2, $3 "\"" }' OFS="\", \"" inventory.txt
或sed
解决方案:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);
my ($customer, $name);
while (<>) {
if (/Customer ID=(.*), Customer Name=(.*)/) {
($customer, $name) = ($1, $2);
} elsif (/Inventory ID=(.*), Inventory Name=(.*)/) {
say join ', ' => map qq("$_"), $customer, $name, $1, $2;
}
}
sed -n '/^Customer ID/ h; /^Inventory ID/ { G; s/.*=\([^,]*\).*=\([^\n]*\).*=\([^,]*\).*=\(.*\)/"\3", "\4", "\1", "\2"/; p }' inventory.txt
结果:
"9000", "Acme, Inc", "INV_ID1", "Acme_INV1"
"9000", "Acme, Inc", "INV_ID2", "Acme_INV2"
"7500", "Anvil, Corp", "INV_ID3", "Anvil_INV1"
awk
说明:
OFS="\", \"" # set the output field separator to: ", "
-F= # split the line into three fields using the '=' character
{ sub(/,.*/,"",$2) } # one each line of input, remove everything trailing a
# comma from field two.
/^Customer ID/ { ... } # if the line starts with 'Customer ID'; do
r = $2 OFS $3 # build a record using field two and three separated by 'OFS'
/^Inventory ID/ {...} # if the line starts with 'Inventory ID'; do
print "\"" r, $2, $3 "\"" # print out a double-quote, the record, OFS, $2, OFS,
# $3 and lastly a double quote
sed
说明:
OFS="\", \"" # set the output field separator to: ", "
-F= # split the line into three fields using the '=' character
{ sub(/,.*/,"",$2) } # one each line of input, remove everything trailing a
# comma from field two.
/^Customer ID/ { ... } # if the line starts with 'Customer ID'; do
r = $2 OFS $3 # build a record using field two and three separated by 'OFS'
/^Inventory ID/ {...} # if the line starts with 'Inventory ID'; do
print "\"" r, $2, $3 "\"" # print out a double-quote, the record, OFS, $2, OFS,
# $3 and lastly a double quote
使用-n
标志禁用默认打印。当一行以“客户ID”开头时,复制该行以保留空间。当找到以“Inventory ID”开头的行时,将保留空间追加到当前行。使用一些神奇的正则表达式来重新排列不同的字段并修复格式
这里有一种使用awk的方法:
awk -F= '{ sub(/,.*/,"",$2) } /^Customer ID/ { r = $2 OFS $3 } /^Inventory ID/ { print "\"" r, $2, $3 "\"" }' OFS="\", \"" inventory.txt
或sed
解决方案:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);
my ($customer, $name);
while (<>) {
if (/Customer ID=(.*), Customer Name=(.*)/) {
($customer, $name) = ($1, $2);
} elsif (/Inventory ID=(.*), Inventory Name=(.*)/) {
say join ', ' => map qq("$_"), $customer, $name, $1, $2;
}
}
sed -n '/^Customer ID/ h; /^Inventory ID/ { G; s/.*=\([^,]*\).*=\([^\n]*\).*=\([^,]*\).*=\(.*\)/"\3", "\4", "\1", "\2"/; p }' inventory.txt
结果:
"9000", "Acme, Inc", "INV_ID1", "Acme_INV1"
"9000", "Acme, Inc", "INV_ID2", "Acme_INV2"
"7500", "Anvil, Corp", "INV_ID3", "Anvil_INV1"
awk
说明:
OFS="\", \"" # set the output field separator to: ", "
-F= # split the line into three fields using the '=' character
{ sub(/,.*/,"",$2) } # one each line of input, remove everything trailing a
# comma from field two.
/^Customer ID/ { ... } # if the line starts with 'Customer ID'; do
r = $2 OFS $3 # build a record using field two and three separated by 'OFS'
/^Inventory ID/ {...} # if the line starts with 'Inventory ID'; do
print "\"" r, $2, $3 "\"" # print out a double-quote, the record, OFS, $2, OFS,
# $3 and lastly a double quote
sed
说明:
OFS="\", \"" # set the output field separator to: ", "
-F= # split the line into three fields using the '=' character
{ sub(/,.*/,"",$2) } # one each line of input, remove everything trailing a
# comma from field two.
/^Customer ID/ { ... } # if the line starts with 'Customer ID'; do
r = $2 OFS $3 # build a record using field two and three separated by 'OFS'
/^Inventory ID/ {...} # if the line starts with 'Inventory ID'; do
print "\"" r, $2, $3 "\"" # print out a double-quote, the record, OFS, $2, OFS,
# $3 and lastly a double quote
使用-n
标志禁用默认打印。当一行以“客户ID”开头时,复制该行以保留空间。当找到以“Inventory ID”开头的行时,将保留空间追加到当前行。使用一些神奇的正则表达式来重新排列不同的字段并修复格式
另一个awk一个班轮,不使用FS
awk -vq="\"" '/^(Cus|Inv)/{f=$0~/^Cus/;gsub(/[^,]*=/,q);sub(/,/,q",");c=f?$0q:c;if(!f)print c","$0q}' file
测试:
另一个awk一个班轮,不使用FS
awk -vq="\"" '/^(Cus|Inv)/{f=$0~/^Cus/;gsub(/[^,]*=/,q);sub(/,/,q",");c=f?$0q:c;if(!f)print c","$0q}' file
测试:
这可能适用于您(GNU-sed):
这可能适用于您(GNU-sed):
对函数使用gawk扩展
输出
"9000","Acme, Inc","INV_ID1","Acme_INV1"
"9000","Acme, Inc","INV_ID2","Acme_INV2"
"7500","Anvil, Corp","INV_ID3","Anvil_INV1"
对函数使用gawk扩展
输出
"9000","Acme, Inc","INV_ID1","Acme_INV1"
"9000","Acme, Inc","INV_ID2","Acme_INV2"
"7500","Anvil, Corp","INV_ID3","Anvil_INV1"
你应该考虑客户姓名有逗号。该死,你又揍了我一顿。1.你能评论一下你的代码在做什么吗?我对BASH脚本比较陌生。提前谢谢!当然,我会在一分钟内添加关于awk
解决方案的解释。但正如您所看到的,我添加了一个sed
解决方案。我只是想看看是否可以先减少正则表达式,使其更具可读性。我认为这是可以做到的。这太棒了!!非常感谢您提供这两种解决方案。我正在根据自己的需要配置SED解决方案。非常感谢您的帮助!!:)你应该考虑客户姓名有逗号。该死,你又揍了我一顿。1.你能评论一下你的代码在做什么吗?我对BASH脚本比较陌生。提前谢谢!当然,我会在一分钟内添加关于awk
解决方案的解释。但正如您所看到的,我添加了一个sed
解决方案。我只是想看看是否可以先减少正则表达式,使其更具可读性。我认为这是可以做到的。这太棒了!!非常感谢您提供这两种解决方案。我正在根据自己的需要配置SED解决方案。非常感谢您的帮助!!:)这在sed中很棘手,可能是不可能的。我一直在尝试设想一种方法,使用sed的“保留空间”保留客户ID和姓名的副本,然后针对每个库存行,将相关数据附加到保留空间并打印,但似乎任何对保留空间的使用都会修改它,从而使特定客户的第二个(或更多)库存行的保留空间无效。虽然在sed
中努力寻找实现这一点的方法既有趣又有教育意义,但如果你只是想完成这项工作,steve的awk one liner看起来会奏效。这在sed中很棘手,而且可能是不可能的。我一直在尝试设想一种方法,使用sed的“保留空间”保留客户ID和姓名的副本,然后针对每个库存行,将相关数据附加到保留空间并打印,但似乎任何对保留空间的使用都会修改它,从而使特定客户的第二个(或更多)库存行的保留空间无效。虽然在sed
中努力寻找实现这一点的方法既有趣又有教育意义,但如果你只是想完成这项工作,steve的awk one liner看起来会奏效。