Shell-Script

文本處理:提取文件的一部分並將它們寫入一行

  • April 1, 2017

我有幾個格式如下的文件:

...
<title> Field1 : DATA_FIELD_1</title>
...
<i class="blablabla"></i> <b>Field2 : </b> <span>DATA_FIELD_2</span>
...
<i class="blablabla"></i> <b>Field3 : </b> <span>DATA_FIELD_3</span>
...
<i class="blablabla"></i> <b>Field4 : </b> <span>DATA_FIELD_4</span >
...
<i class="blablabla"></i> <b>Field5 : </b> <span>DATA_FIELD_5 </span>
...

我想讀取每個文件,獲取每個欄位的數據,然後以管道分隔格式將其寫入新文件。

例如:

FileID | Field1 | Field2 | Field3 | Field4 | Field5
1 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
2 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
3 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
4 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5

我設法使用以下命令使用 grep 不正確地提取數據:

grep -o 'Field1 : .*\|Field2 : .*\|Field3 : .*\|Field4 : .*\|Field5 : .*' File-* >> NewFile

但這是我得到的結果

File-1:Field1 : DATA_FIELD_1</title>
File-1:Field2 : </b> <span>DATA_FIELD_2</span>
File-1:Field3 : </b> <span>DATA_FIELD_3</span>
File-1:Field4 : </b> <span>DATA_FIELD_4</span >
File-1:Field5 : </b> <span>DATA_FIELD_5 </span>
File-2:Field1 : DATA_FIELD_1</title>
File-2:Field2 : </b> <span>DATA_FIELD_2</span>
File-2:Field3 : </b> <span>DATA_FIELD_3</span>
File-2:Field4 : </b> <span>DATA_FIELD_4</span >
File-2:Field5 : </b> <span>DATA_FIELD_5 </span>
File-3:Field1 : DATA_FIELD_1</title>
File-3:Field2 : </b> <span>DATA_FIELD_2</span>
File-3:Field3 : </b> <span>DATA_FIELD_3</span>
File-3:Field4 : </b> <span>DATA_FIELD_4</span >
File-3:Field5 : </b> <span>DATA_FIELD_5 </span>

通常,使用正則表達式處理 HTML/XML 是一個壞主意,因為它們的表達能力不足以處理所有極端情況。但是,您的 grep 輸出表明我們可以在您的確切情況下。

這是一種使用 sed 處理從 grep 命令獲得的輸出的方法:

sed -e 'N;N;N;N;s/^File-\(.*\):Field1 : \(.*\)<\/title>.*Field2 : .*<span>\(.*\)<\/span *>.*Field3 : .*<span>\(.*\)<\/span *>.*Field4 : .*<span>\(.*\)<\/span *>.*Field5 : .*<span>\(.*\)\s*<\/span *>/\1 | \2 | \3 | \4 | \5 | \6/'

說明:

  • N;N;N;N;:這用於連接五到五行(以便將文件中的所有欄位放在同一行中)
  • s/:這會啟動一個替換命令,第一部分是匹配,第二部分是替換
  • ^File-\(.*\):: 這匹配文件號
  • Field1 : \(.*\)<\/title>: 這匹配第一個欄位
  • .*Field2 : .*<span>\(.*\)<\/span *>: 這與第二個匹配
  • /\1 | \2 | \3 / \4 | \5 | \6/:這是替換部分:第一\(.*\)部分中\1\2

結果:

1 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5 
2 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5 
3 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5

另一種可能的方法是使用 XML 處理器。在這種情況下,XMLstarlet。

xmlstarlet sel -t -v 'substring-after(//title,":")' \
                 -m //span -o "|" -v .  \
              -t -n  *.xml

在哪裡:

  • sel -t– 根據以下模板選擇 XML 部分
  • -v 'substring-after(//title,":")'– 是 “:” 後面的 title 的值
  • -m //span -o "|" -v . – 匹配span並列印“|” 及其價值
  • -t -n– 添加一個換行符

引用自:https://unix.stackexchange.com/questions/354669