1

inventory.txt数百行を含むファイルがあります。顧客ID/名前、在庫ID /名前、および製品ID/名前に関連するデータが一覧表示されます。任意の行にcustomerId=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、または十分に機能する代替手段を使用してやりたいのは、顧客ID/名前と在庫ID/名前だけを含む顧客/在庫の組み合わせごとに1行のデータを含むCSV形式のファイルを作成することです。田畑。したがって、出力は次のようになります。

"9000", "Acme, Inc.", "INV_ID1", "Acme_INV1"
"9000", "Acme, Inc.", "INV_ID2", "Acme_INV2"
"7500", "Anvil, Inc.", "INV_ID3", "Anvil_INV1"

SEDを使用して、入力データをコンマと引用符でCSVファイル出力にフォーマットする方法を理解していますが、すべての行の先頭でとを強制Customer IDCustomer Nameに繰り返す方法を理解するのに問題があります。Inventory IDInventory Name

4

5 に答える 5

2

使用する1つの方法は次のawkとおりです。

awk -F= '{ sub(/,.*/,"",$2) } /^Customer ID/ { r = $2 OFS $3 } /^Inventory ID/ { print "\"" r, $2, $3 "\"" }' OFS="\", \"" inventory.txt

またはsed解決策:

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説明:

-nフラグを使用してデフォルトの印刷を無効にします。「顧客ID」で始まる行の場合は、スペースを確保するためにその行をコピーします。「在庫ID」で始まる行が見つかったら、現在の行に保留スペースを追加します。いくつかの魔法の正規表現を使用して、さまざまなフィールドを再配置し、フォーマットを修正します。

于 2013-01-11T14:28:47.993 に答える
1

これはあなたのために働くかもしれません(GNU sed):

sed -r '/^Customer/{h;d};/^Inventory/!d;G;s/.*=([^,]*).*=([^\n]*).*=([^,]*).*=(.*)/"\3", "\4", "\1", "\2"/' file
于 2013-01-11T15:13:21.460 に答える
1

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;
    }
}
于 2013-01-11T14:17:56.340 に答える
1

FSを使用しない別のawkワンライナー

awk -vq="\"" '/^(Cus|Inv)/{f=$0~/^Cus/;gsub(/[^,]*=/,q);sub(/,/,q",");c=f?$0q:c;if(!f)print c","$0q}' file

テスト:

kent$  echo "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"|awk -vq="\"" '/^(Cus|Inv)/{f=$0~/^Cus/;gsub(/[^,]*=/,q);sub(/,/,q",");c=f?$0q:c;if(!f)print c","$0q}'                                   
"9000","Acme, Inc","INV_ID1","Acme_INV1"
"9000","Acme, Inc","INV_ID2","Acme_INV2"
"7500","Anvil, Corp","INV_ID3","Anvil_INV1"
于 2013-01-11T14:57:42.973 に答える
0

関数にgawk拡張機能を使用match()する

gawk '
    match($0, /^Customer ID=([^,]+), Customer Name=(.*)/, cust) {
        c_id=cust[1]; c_name=cust[2]
        next
    }
    match($0, /^Inventory ID=([^,]+), Inventory Name=(.*)/, inv) {
        printf "\"%s\",\"%s\",\"%s\",\"%s\"\n", c_id, c_name, inv[1], inv[2]
    }
' filename

出力

"9000","Acme, Inc","INV_ID1","Acme_INV1"
"9000","Acme, Inc","INV_ID2","Acme_INV2"
"7500","Anvil, Corp","INV_ID3","Anvil_INV1"
于 2013-01-11T16:30:01.887 に答える