Sed
在不依賴 html 實體的情況下進行過濾,基於開始結束匹配的一行巨大字元串,並將文本保持在模式之間,無論長度如何
我有一個像Pastebin這樣的單行文件,但要長得多。
我的目標是僅過濾
example1 的部分字元串:
<a
以</a>
example2 開頭:以
PZ
end開頭s16
,因此在每種情況下都將文本保持在匹配之間而不依賴於 html 實體
我在一個
FreeBSD
並且我已經有一個依賴於 html 實體的解決方法
- 美化為多行
tidy -i -m -w 160 -ashtml -utf8 ~/file
- 如果不包含字元串,則刪除行
sed -i '' '/\<\/a\>/!d' ~/file
順便說一句,我試圖在不依賴 html 實體的情況下執行直接過濾器。現在我只能得到一個匹配的確切開始,但我不知道我過濾的字元串內容有多長,所以我不能精確到匹配的結束,查看意外結果步驟來重現
重現意外結果的步驟
wget -O ~/file https://pastebin.com/raw/xbti369J
grep -E -o ".{0,0}PZ.{0,46}" ~/file
因為我們要求固定長度,所以我們得到了錯誤的行
PZ</td><td class="s15">€ 1.20</td><td class="s16 PZ</td><td class="s15"></td><td class="s16">A</t
目標是獲得線條結果模式,無論長度如何,如下所示
PZ</td><td class="s15">€ 1.20</td><td class="s16 PZ</td><td class="s15"></td><td class="s16
如果要選擇從 a
PZ
到最近的每個片段s16
,則需要非貪婪匹配,grep
(擴展的)正則表達式不支持該匹配,但 GNU為 Perl 樣式表達式grep
提供了-P
erl 選項:grep -P -o "PZ.*?s16" ~/file
Perl 表達式 `.*?’ 代表將使整個表達式匹配的任何字元的最短匹配。
這可能仍然不是您要查找的內容,因為
PZ
匹配項內部還有更多內容,但是據我了解您的範例,您只想要那些PZ
後面s16
沒有其他匹配項的內容PZ
。所以讓我們在第二步中刪除不需要的東西:grep -P -o "PZ.*?s16" ~/file | sed 's/.*PZ/PZ/'
您想使用 XML 解析器,例如
xmllint
.使用下面的 XPath 表達式過濾掉
a
元素之間的文本:xmllint --html --xpath '//a/text()' <file>