簡體   English   中英

使用帶分隔符的 AWK 打印特定列

[英]Use AWK with delimiter to print specific columns

我的文件如下所示:

+------------------------------------------+---------------+----------------+------------------+------------------+-----------------+
| Message                                  | Status        | Adress         | Changes          | Test             | Calibration     |
|------------------------------------------+---------------+----------------+------------------+------------------+-----------------|
| Hello World                              | Active        | up             |                1 |               up |            done |
| Hello Everyone Here                      | Passive       | up             |                2 |             down |            none |
| Hi there. My name is Eric. How are you?  | Down          | up             |                3 |         inactive |            done |
+------------------------------------------+---------------+----------------+------------------+------------------+-----------------+
+----------------------------+---------------+----------------+------------------+------------------+-----------------+
| Message                    | Status        | Adress         | Changes          | Test             | Calibration     |
|----------------------------+---------------+----------------+------------------+------------------+-----------------|
| What's up?                 | Active        | up             |                1 |               up |            done |
| Hi. I'm Otilia             | Passive       | up             |                2 |             down |            none |
| Hi there. This is Marcus   | Up            | up             |                3 |         inactive |            done |
+----------------------------+---------------+----------------+------------------+------------------+-----------------+

我想使用 AWK 提取特定列。我可以使用 CUT 來完成; 但是,當每個表的長度根據每列中存在的字符數而變化時,我沒有得到所需的 output。

cat File.txt | cut -c -44
+------------------------------------------+
| Message                                  |
|------------------------------------------+
| Hello World                              |
| Hello Everyone Here                      |
| Hi there. My name is Eric. How are you?  |
+------------------------------------------+
+----------------------------+--------------
| Message                    | Status
|----------------------------+--------------
| What's up?                 | Active
| Hi. I'm Otilia             | Passive
| Hi there. This is Marcus   | Up
+----------------------------+--------------

或者

cat File.txt | cut -c 44-60
+---------------+
| Status        |
+---------------+
| Active        |
| Passive       |
| Down          |
+---------------+
--+--------------
  | Adress
--+--------------
  | up
  | up
  | up
--+--------------

我嘗試使用 AWK 但我不知道如何添加 2 個不同的分隔符來處理所有行。

cat File.txt | awk 'BEGIN {FS="|";}{print $2,$3}'

 Message                                    Status
------------------------------------------+---------------+----------------+------------------+------------------+-----------------
 Hello World                                Active
 Hello Everyone Here                        Passive
 Hi there. My name is Eric. How are you?    Down


 Message                      Status
----------------------------+---------------+----------------+------------------+------------------+-----------------
 What's up?                   Active
 Hi. I'm Otilia               Passive
 Hi there. This is Marcus     Up

我要找的output:

+------------------------------------------+
| Message                                  |
|------------------------------------------+
| Hello World                              |
| Hello Everyone Here                      |
| Hi there. My name is Eric. How are you?  |
+------------------------------------------+
+----------------------------+
| Message                    |
|----------------------------+
| What's up?                 | 
| Hi. I'm Otilia             | 
| Hi there. This is Marcus   | 
+----------------------------+

或者

+------------------------------------------+---------------+
| Message                                  | Status        |
|------------------------------------------+---------------+
| Hello World                              | Active        |
| Hello Everyone Here                      | Passive       |
| Hi there. My name is Eric. How are you?  | Down          |
+------------------------------------------+---------------+
+----------------------------+---------------+
| Message                    | Status        | 
|----------------------------+---------------+
| What's up?                 | Active        | 
| Hi. I'm Otilia             | Passive       | 
| Hi there. This is Marcus   | Up            | 
+----------------------------+---------------+

或隨機其他列

+------------------------------------------+----------------+------------------+
| Message                                  | Adress         | Test             |
|------------------------------------------+----------------+------------------+
| Hello World                              | up             |               up |
| Hello Everyone Here                      | up             |             down |
| Hi there. My name is Eric. How are you?  | up             |         inactive |
+------------------------------------------+----------------+------------------+
+----------------------------+---------------+------------------+
| Message                    |Adress         | Test             |
|----------------------------+---------------+------------------+
| What's up?                 |up             |               up |
| Hi. I'm Otilia             |up             |             down |
| Hi there. This is Marcus   |up             |         inactive |
+----------------------------+---------------+------------------+

提前致謝。

使用GNU awk一個想法:

awk -v fldlist="2,3" '
BEGIN { fldcnt=split(fldlist,fields,",") }                      # split fldlist into array fields[]

      { split($0,arr,/[|+]/,seps)                               # split current line on dual delimiters "|" and "+"
        for (i=1;i<=fldcnt;i++)                                 # loop through our array of fields (fldlist)
            printf "%s%s", seps[fields[i]-1], arr[fields[i]]    # print leading separator/delimiter and field
        printf "%s\n", seps[fields[fldcnt]]                     # print trailing separator/delimiter and terminate line
      }
' File.txt

筆記:

  • split() function 的第 4 個參數需要GNU awkseps == 分隔符數組;有關詳細信息,請參閱gawk 字符串函數
  • 假設我們的字段分隔符( |+ )不顯示為數據的一部分
  • 輸入變量fldlist是一個逗號分隔的列列表,模擬將傳遞給cut的內容(例如,當一行以分隔符開頭時,字段 #1 為空白)

對於fldlist="2,3"這會生成:

+------------------------------------------+---------------+
| Message                                  | Status        |
|------------------------------------------+---------------+
| Hello World                              | Active        |
| Hello Everyone Here                      | Passive       |
| Hi there. My name is Eric. How are you?  | Down          |
+------------------------------------------+---------------+
+----------------------------+---------------+
| Message                    | Status        |
|----------------------------+---------------+
| What's up?                 | Active        |
| Hi. I'm Otilia             | Passive       |
| Hi there. This is Marcus   | Up            |
+----------------------------+---------------+

對於fldlist="2,4,6"這會生成:

+------------------------------------------+----------------+------------------+
| Message                                  | Adress         | Test             |
|------------------------------------------+----------------+------------------+
| Hello World                              | up             |               up |
| Hello Everyone Here                      | up             |             down |
| Hi there. My name is Eric. How are you?  | up             |         inactive |
+------------------------------------------+----------------+------------------+
+----------------------------+----------------+------------------+
| Message                    | Adress         | Test             |
|----------------------------+----------------+------------------+
| What's up?                 | up             |               up |
| Hi. I'm Otilia             | up             |             down |
| Hi there. This is Marcus   | up             |         inactive |
+----------------------------+----------------+------------------+

對於fldlist="4,3,2"這會生成:

+----------------+---------------+------------------------------------------+
| Adress         | Status        | Message                                  |
+----------------+---------------|------------------------------------------+
| up             | Active        | Hello World                              |
| up             | Passive       | Hello Everyone Here                      |
| up             | Down          | Hi there. My name is Eric. How are you?  |
+----------------+---------------+------------------------------------------+
+----------------+---------------+----------------------------+
| Adress         | Status        | Message                    |
+----------------+---------------|----------------------------+
| up             | Active        | What's up?                 |
| up             | Passive       | Hi. I'm Otilia             |
| up             | Up            | Hi there. This is Marcus   |
+----------------+---------------+----------------------------+

再說一次? ( fldlist="3,3,3" ):

+---------------+---------------+---------------+
| Status        | Status        | Status        |
+---------------+---------------+---------------+
| Active        | Active        | Active        |
| Passive       | Passive       | Passive       |
| Down          | Down          | Down          |
+---------------+---------------+---------------+
+---------------+---------------+---------------+
| Status        | Status        | Status        |
+---------------+---------------+---------------+
| Active        | Active        | Active        |
| Passive       | Passive       | Passive       |
| Up            | Up            | Up            |
+---------------+---------------+---------------+

如果您錯誤地嘗試打印“第一”列,即fldlist="1"

+
|
|
|
|
|
+
+
|
|
|
|
|
+

如果GNU awk可用,請嘗試 markp-fuso 的 nice 解決方案。 如果沒有,這里有一個符合 posix 標准的替代方案:

#!/bin/bash

# define bash variables
cols=(2 3 6)                            # bash array of desired columns
col_list=$(IFS=,; echo "${cols[*]}")    # create a csv string

awk -v cols="$col_list" '
NR==FNR {
    if (match($0, /^[|+]/)) {           # the record contains a table
        if (match($0, /^[|+]-/))        # horizontally ruled line
            n = split($0, a, /[|+]/)    # split into columns
        else                            # "cell" line
            n = split($0, a, /\|/)
        len = 0
        for (i = 1; i < n; i++) {
            len += length(a[i]) + 1     # accumulated column position
            pos[FNR, i] = len
        }
    }
    next
}
{
    n = split(cols, a, /,/)             # split the variable `cols` on comma into an array
    for (i = 1; i <= n; i++) {
        col = a[i]
        if (pos[FNR, col] && pos[FNR, col+1]) {
            printf("%s", substr($0, pos[FNR, col], pos[FNR, col + 1] - pos[FNR, col]))
        }
    }
    print(substr($0, pos[FNR, col + 1], 1))
}
' file.txt file.txt

cols=(2 3 6)的結果如上所示:

+---------------+----------------+-----------------+
| Status        | Adress         | Calibration     |
+---------------+----------------+-----------------|
| Active        | up             |            done |
| Passive       | up             |            none |
| Down          | up             |            done |
+---------------+----------------+-----------------+
+---------------+----------------+-----------------+
| Status        | Adress         | Calibration     |
+---------------+----------------+-----------------|
| Active        | up             |            done |
| Passive       | up             |            none |
| Up            | up             |            done |
+---------------+----------------+-----------------+

它在第 1 遍中檢測列寬,然后在第 2 遍中拆分列 position 上的行。
您可以使用在腳本開頭分配的 bash 數組cols控制要打印的列。 請按遞增順序將數組分配給所需列號的列表。 如果您想以不同的方式使用 bash 變量,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM