2017-09-26 16 views
0

我有一個文件格式如下。任何人都可以在列中轉換它? 我已經嘗試過下面的awk命令,但是如果一個客戶有多個主機名,它會創建更多的4列。如何使用shell腳本在行和列中轉換我的文件

awk '/"customer_name":/{if (x)print x;x="";}{x=(!x)?$0:x","$0;}END{print x;}' filename 

輸入:

customer_name: "abc" 
    "HostName": "tm-1" 
    "LastDayRxBytes": 0 
    "Status": "offline" 
    "HostName": "tm-2" 
    "LastDayRxBytes": 0 
    "Status": "offline" 
    "HostName": "tm-3" 
    "LastDayRxBytes": 0 
    "Status": "offline" 
    "HostName": "new-va-threat-01" 
    "LastDayRxBytes": 0 
    "Status": "offline" 
customer_name: "xyz" 
    "HostName": "tm-56" 
    "LastDayRxBytes": 10708747 
    "Status": "ok" 
customer_name: "def" 
customer_name: "uvw" 
    "HostName": "tm-23" 
    "LastDayRxBytes": 34921829912 
    "Status": "ok" 
customer_name: "new cust" 
    "HostName": "tm-1-3" 
    "LastDayRxBytes": 33993187093 
    "Status": "ok" 
customer_name: "a12 d32 ffg" 
customer_name: "bcd abc" 
customer_name: "mno opq" 
customer_name: "abc dhg pvt ltd." 
    "HostName": "tm-10" 
    "LastDayRxBytes": 145774401010 
    "Status": "ok" 
    "HostName": "tm-ngtm-13" 
    "LastDayRxBytes": 150159680874 
    "Status": "ok" 
    "HostName": "new-ngtm-11" 
    "LastDayRxBytes": 207392526747 
    "Status": "ok" 
    "HostName": "old-ngtm-06" 
    "LastDayRxBytes": 17708734533 
    "Status": "ok" 
    "HostName": "tm-08" 
    "LastDayRxBytes": 559289251 
    "Status": "ok" 
    "HostName": "tm-12" 
    "LastDayRxBytes": 534145552271 
    "Status": "ok" 

我希望它在柱被打印和行爲:

Column 1    Column 2    Column 3    Column 4 
CustName    Host     Last RX    Status 
abc     tm-1     0     offline 
abc     tm-2     0     offline 
abc     tm-3     0     offline 
abc     new-va-threat-01  0     offline 
xyz     tm-56    10708747    ok 
def      
uvw     tm-23    34921829912   ok 
new_cust    tm-1-3    33993187093   ok 
a12 d32 ffg 
acd abc 
mno opq 
abc dhg pvt ltd.  tm-10    145774401010   ok 
abc dhg pvt ltd.  tm-ngtm-13   150159680874   ok 
abc dhg pvt ltd.  new-ngtm-11   207392526747   ok 
abc dhg pvt ltd.  old-ngtm-06   17708734533   ok 
abc dhg pvt ltd.  tm-08    559289251   ok 
abc dhg pvt ltd.  tm-12    534145552271   ok 
+0

Column4 \t欄3 \t欄3 \t Column4 客戶名稱\t主機名\t收到\t狀態 ABC \t TM-1 離線 ABC \t TM-2 離線 ABC \t TM-3 離線 abc \t new-va-threat-01 offline xyz \t tm-56 OK DEF \t \t \t UVW \t TM-23 \t \t 34921829912確定 新CUST \t TM-1-3 \t \t 33993187093確定 A12 D32 FFG \t \t \t BCD ABC \t \t \t MNO OPQ \t \t \t abc dhg pvt ltd。 \t tm-10 \t 1.45774E + 11 \t ok abc dhg pvt ltd。 \t tm-ngtm-13 \t 1.5016E + 11 \t ok abc dhg pvt ltd。 \t new-ngtm-11 \t 2.07393E + 11 \t ok abc dhg pvt ltd。 \t old-ngtm-06 ok abc dhg pvt ltd。 \t tm-08 ok abc dhg pvt ltd。 \t tm-12 \t 5.34146E + 11 \t ok – Majeed

+1

該評論中是否有任何非顯而易見的含義?如果是,請編輯您的問題以傳達它。 – Yunnosch

+0

您的任何字符串是否可以包含':'或':'?怎麼樣逃脫'''(例如''''或''''')? –

回答

1

我會寫這個

awk -F": " -v OFS="\t" ' 
    BEGIN {print "CustName", "Host", "Last RX", "Status"} 
    { 
     gsub(/"/,"") 
     sub(/^[[:blank:]]+/,"") 
    } 
    $1 == "customer_name" { 
     if ("customer_name" in data && !have_data) 
      print data["customer_name"] 
     have_data = 0 
    } 
    { 
     data[$1] = $2 
    } 
    ("HostName" in data) && ("LastDayRxBytes" in data) && ("Status" in data) { 
     print data["customer_name"], data["HostName"], data["LastDayRxBytes"], data["Status"] 
     delete data["HostName"] 
     delete data["LastDayRxBytes"] 
     delete data["Status"] 
     have_data = 1 
    } 
' file | column -s $'\t' -t 
CustName   Host    Last RX  Status 
abc    tm-1    0    offline 
abc    tm-2    0    offline 
abc    tm-3    0    offline 
abc    new-va-threat-01 0    offline 
xyz    tm-56    10708747  ok 
def 
uvw    tm-23    34921829912 ok 
new cust   tm-1-3   33993187093 ok 
a12 d32 ffg 
bcd abc 
mno opq 
abc dhg pvt ltd. tm-10    145774401010 ok 
abc dhg pvt ltd. tm-ngtm-13  150159680874 ok 
abc dhg pvt ltd. new-ngtm-11  207392526747 ok 
abc dhg pvt ltd. old-ngtm-06  17708734533 ok 
abc dhg pvt ltd. tm-08    559289251  ok 
abc dhg pvt ltd. tm-12    534145552271 ok 
+0

謝謝格倫它的作品! 我真的很感激你的快速幫助。 我有一個查詢,我把它輸出到csv文件中,它帶有1個標籤空格的列。 無論如何,我們可以在列A,主列B等中打印它的custname嗎? – Majeed

+0

如果你拿出'|列-s $'\ t'-t'部分,您將剩下以製表符分隔的列。 –

+0

非常感謝Glenn,它創造了奇蹟。 – Majeed

0

Perl來救援:

perl -lne ' 
    if (/customer_name: "(.*)"/) { 
     print $h{name} unless $h{printed} || !%h; 
     undef $h{printed} if $1 ne $h{name}; 
     $h{name} = $1; 
    } else { 
     /"([^"]+)": "?([^"]+)"?/ and $h{$1} = $2; 
     $h{printed} = print join "\t", 
      @h{qw{ name HostName LastDayRxBytes Status }} 
      if "Status" eq $1; 
    } 
    END { print $h{name} unless $h{printed} || !%h } 
    ' < input_file 
  • %h散列用於收集有關要打印的行的信息。
  • 讀取客戶名稱時,如果還沒有打印過,則會打印先前的客戶名稱。同樣的情況發生在輸入的最後,以打印可能的最後一個客戶而沒有詳細信息。
  • 讀取狀態時會打印一行。
0

GNU AWK溶液:

$ cat tst.awk 
BEGIN { 
    RS="customer_name: " 
    pr("Column1", "Column2", "Column3", "Column4") 
    pr("Custname", "Host", "Last RX", "Status") 
} 
match($0, /"([^"]+)"/, cust) { 
    printed=0 
    str=substr($0, RLENGTH+2) 
    while (match(str, /"HostName":\s"([^"]+)"\s+"LastDayRxBytes":\s(\S+)\s+"Status":\s"([^"]+)"\s/, col)){ 
     str=substr(str, RLENGTH+3) 
     pr(cust[1], col[1], col[2], col[3]) 
     printed=1 
    } 
    if (!printed) pr(cust[1]) 
} 
function pr(cust,host,rx,status) { 
    printf "%-16s\t%-16s\t%-16s\t%-10s\n", cust, host, rx, status 
} 

基於示例性輸入,可以使用正則表達式處理這一個和匹配功能也是如此。測試它:

$ awk -f tst.awk input.txt 
Column1    Column2    Column3    Column4 
Custname   Host    Last RX    Status 
abc     tm-1    0     offline 
abc     tm-2    0     offline 
abc     tm-3    0     offline 
abc     new-va-threat-01 0     offline 
xyz     tm-56    10708747   ok 
def 
uvw     tm-23    34921829912   ok 
new cust   tm-1-3    33993187093   ok 
a12 d32 ffg 
bcd abc 
mno opq 
abc dhg pvt ltd. tm-10    145774401010  ok 
abc dhg pvt ltd. tm-ngtm-13   150159680874  ok 
abc dhg pvt ltd. new-ngtm-11   207392526747  ok 
abc dhg pvt ltd. old-ngtm-06   17708734533   ok 
abc dhg pvt ltd. tm-08    559289251   ok 
abc dhg pvt ltd. tm-12    534145552271  ok 

說明:

  • 記錄分隔符RS設置在customer_name:,所以$ 0包含每個客戶的所有主機,RX和狀態信息。
  • 第一場比賽與正則表達式"([^"]+)"將捕獲客戶
  • 第二場比賽與正則表達式"HostName":\s"([^"]+)"\s+"LastDayRxBytes":\s(\S+)\s+"Status":\s"([^"]+)"\s將捕獲主機名,rx和狀態。
  • 如果第二場比賽成功,請縮短您想在下一場比賽中使用的字符串。

我知道,這不是awk way的處理方式,但是輸入的常規格式再次允許這個 - 非常簡潔 - 基於正則表達式的解決方案。

相關問題