簡體   English   中英

用於從帶有可選字符 ~ 的字符串中捕獲路徑的正則表達式 (perl|awk|sed|..)

[英]regex for capturing path from a string with optional character ~ (perl|awk|sed|..)

我想匹配第一個和最后一個斜杠之間的所有內容/包括可選的~在第一個斜杠之前。

我在第一部分使用了這個:

echo ~~a~/dir1/di r2/b.c \
| perl -pe 's/[^\/]*(\/.*\/).*/\1/'

產生/dir1/di r2/

這場比賽包括波浪號:

perl -pe 's/ .* ( ~ \\/.*\\/).*/\\1/'

但添加? 在這些情況下,對於可選字符似乎不起作用:

perl -pe 's/ .* ( ~? \\/.*\\/).*/\\1/' -> /di r2/
perl -pe 's/ .* ( (?:~) \\/.*\\/).*/\\1/' -> ~~a/dir1/di r2/bc

我做錯了什么?

如果我正確理解了所需的輸出,無論是否使用波浪號,這都適用於我

echo "path /d1/d2/43a/" | perl -nE 'm{ ( ~? (?: /.*/ | /) ) }x; say "$1"'

版畫

/d1/d2/43a/

相同的 Perl 代碼,在輸入的第一個斜杠前有一個波浪號

echo "path ~/d1/d2/43a/" | perl -nE 'm{ ( ~? (?: /.*/ | /) ) }x; say "$1"'

版畫

~/d1/d2/43a/

注釋不推薦在替換中使用/1 請改用$1 使用{}作為分隔符,我們不必轉義/ ,使其更具可讀性(而使用除//以外的分隔符時,我們不能在前面省略m )。 否則,在使用/作為分隔符然后將其轉義到內部時,同樣有效。


更新

為了同時捕獲一個單獨的~/ (或/ ),最簡單的更改是顯式添加/.*/ | / /.*/ | / . 為了在這兩種情況下捕獲(可選) ~ ,圍繞此有一個(非捕獲)分組。 刪除了-w標志,因此當輸入字符串根本沒有斜杠時不會發出警告,但只打印一個空行。

原始要求

檔案data

~~a~/dir1/di r2/b.c
/dir1/di r2/z.y
~/dir1/di r3/p.q
gobbledegook~/name/more/still/more/notwanted.c
xxx~//yyy

腳本

perl -ple 's%(?:^.*?)((?:^|~)/.*/).*%$1%' data

示例輸出

~/dir1/di r2/
/dir1/di r2/
~/dir1/di r3/
~/name/more/still/more/
~//

那是你需要的嗎?

剖析正則表達式

s%(?:^.*?)((?:^|~)/.*/).*%$1%

第一部分(?:^.*?)是對行首任意字符序列的非捕獲非貪婪匹配。

第二部分((?:^|~)/.*/)是一個捕獲表達式,它包含一個在行首或波浪號匹配的非捕獲術語,后跟一個斜杠和一個貪婪的任何東西直到最后一個斜線。

尾隨的.*匹配第二部分之后的所有內容。

替換只是捕獲的內容; 剩下的就是 Perl 就是 Perl。


修訂要求

原來的問題陳述似乎是不完整的。 顯然:

對於單斜杠,它應該只輸出/ (如果存在,則帶有伴隨的波浪號)。 對於沒有斜杠,最好是空字符串,因為沒有匹配項。 ... 對於這種情況, ~ab/c/df它返回完整的字符串; 相反,它應該返回/c/

所以,這里有一個修改過的腳本來處理特殊的額外情況(“學習如何釣魚”發生了什么?)。 ~ab/c/df案例丟失了? “字符串開頭或波浪號”分組上的限定符。

修訂的data文件

~~a~/dir1/di r2/b.c
/dir1/di r2/z.y
~/dir1/di r3/p.q
gobbledegook~/name/more/still/more/notwanted.c
xxx~//yyy
not-a-slash-in-sight
just-the-one/with-extra-info
just-the~/with-more-info
~/one-slash-at-start-with-tilde
/one-slash-at-start-without-tilde
~a b/c/d.f

修改腳本

perl -ple 's%^[^/]*$%%; s%(?:^[^/]*?)((?:^|~)?/)[^/]*$%$1%; s%(?:^[^/]*?)((?:^|~)?/.*/).*%$1%' data

對原始表達式的輕微修改放在最后。

第一個s///查找沒有任何/並用空替換它們。

第二個s///查找帶有斜杠的行,前面可能是波浪號或行首,然后是非斜杠到帶有可選波浪號和斜杠的行尾。

匹配事件中前兩個的輸出與第三個s///不匹配。

修訂后的產出

~/dir1/di r2/
/dir1/di r2/
~/dir1/di r3/
~/name/more/still/more/
~//

/
~/
~/
/
/c/

暫無
暫無

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

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