Shell-Script
文本處理:提取文件的一部分並將它們寫入一行
我有幾個格式如下的文件:
... <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
– 添加一個換行符