Shell-Script

如何從一堆文本中過濾路徑列表?

  • January 27, 2022

我有一個包含多個路徑的文本文件 (.txt),我想過濾它們並只留下一個路徑列表。

該文件將是這樣的:

Loremipsumdolorsitametconsecteturadip"/one/path/I_want_to_keep"iscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua
Utenimadminimveniamquisnostrudexercitationul"/another/path/I_want_to_keep"lamcolaborisnisiutaliquipexeacommodoconsequat
Duisauteiruredolorinreprehenderitinvoluptatevelitess"/another/path/I_want_to_keep"ecillumdoloreeufugiatnullapariatur
Excepteursintoccaecatcupidatatnonproident"/another/path/I_want_to_keep"suntinculpaquiofficiadeseruntmollitanimidestlaborum

範例中的路徑有 3 個斜杠 (/),用引號 ("") 括起來,路徑的最後部分是由下劃線 (_) 分隔的幾個單詞,並且周圍的文本沒有特定的模式.

我正在使用 zsh 5.8 (x86_64-apple-darwin21.0)

我提出這個:

% grep -o '"/[^"]*"' file
"/one/path/I_want_to_keep"
"/another/path/I_want_to_keep"
"/another/path/I_want_to_keep"
"/another/path/I_want_to_keep"

perl

perl -lne 'print for grep m{^/.*/.*/}, /"(.*?)"/g' < your-file

將提取帶引號的字元串的內容(假設它們不跨越多行)並 grep 以開頭/並包含至少兩個額外/s` 的內容。

在像這樣的輸入上

"foo"/x/y/"bar"/"/a/b/c"/"/X/Y"

那是foo, bar,/a/b/c/X/Y字元串,只有第三個符合grep()條件,所以我們只得到/a/b/c輸出。看看如何"/x/y/"也沒有報告,因為這/x/y/實際上是在報價之外。

既然你提到zsh,要對運營商做類似的事情zsh,你會這樣做:

set -o extendedglob
string='"foo"/x/y/"bar"/"/a/b/c"/"/X/Y"'

quoted_strings=()
: ${(S)string//(#b)\"(*)\"/${quoted_strings[$#quoted_strings+1]::=$match[1]}}

print -rC1 ${(M)quoted_strings:#/*/*/*}

在哪裡

  • 參數擴展標誌為匹配S打開非貪婪${param//pattern/replacement}匹配。
  • (#b)(我們需要extendedglob)啟用back-references(對於匹配的(*)內容$match[1]
  • ${var::=value}在擴展時無條件地賦值value(Bourne shell的/的一種變體)。我們在這裡使用它來將匹配項附加到數組中。$var``${var-value}``${var:-value}``$quoted_strings
  • print -rC1在olumn上列印其參數raw1 C
  • ${(M)array:#pattern}擴展為匹配的元素(是arrayksh的/的變體,它將整個元素作為一個整體刪除,而不僅僅是前綴 / 後綴,並且參數擴展標誌將其還原(保留匹配項而不是刪除它們)。M``pattern``${var:#pattern}``${var#pattern}``${var%pattern}``M

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