我有一個字串,例如 'home/JOHNSMITH-4991-common-task-list',我想取出大寫部分和它們之間帶有連字符的數字。我對字串進行回顯并將其通過管道傳輸到 sed 就像這樣,但我一直得到我不想要的所有連字符,例如
echo home/JOHNSMITH-4991-common-task-list | sed 's/[^A-Z0-9-]//g'
給我:
JOHNSMITH-4991---
我需要:
JOHNSMITH-4991
如何忽略除第一個連字符以外的所有內容?
謝謝。
uj5u.com熱心網友回復:
您可以使用
sed 's,.*/\([^-]*-[^-]*\).*,\1,'
POSIX BRE 正則運算式詳細資訊:
.*- 任何零個或多個字符/- 一個/字符\([^-]*-[^-]*\)- 第 1 組:除-、連字符之外的任何零個或多個字符,然后是除 之外的零個或多個字符-.*- 任何零個或多個字符
替換是第 1 組占位符\1,以僅恢復捕獲的文本。
請參閱在線演示:
#!/bin/bash
s="home/JOHNSMITH-4991-common-task-list"
sed 's,.*/\([^-]*-[^-]*\).*,\1,' <<< "$s"
# => JOHNSMITH-4991
uj5u.com熱心網友回復:
第一個解決方案:有了awk它會更容易,我們可以保持簡單,請嘗試使用您顯示的樣本進行以下、撰寫和測驗。
echo "echo home/JOHNSMITH-4991-common-task-list" | awk -F'/|-' '{print $2"-"$3}'
解釋:簡單的解釋是,將欄位分隔符設定為/OR-并列印-當前行的第二個欄位和第三個欄位。
第二種解決方案:在這里使用程式的match功能awk。
echo "echo home/JOHNSMITH-4991-common-task-list" |
awk '
match($0,/\/[^-]*-[^-]*/){
print substr($0,RSTART 1,RLENGTH-1)
}'
第三種解決方案:grep在此處使用 GNU解決方案。使用此處的-oP選項,grep使用 o 選項列印匹配的值并使用選項啟用 ERE(擴展正則運算式)P。然后在主程式中grep使用.*/后跟\K忽略先前匹配的部分,然后提到[^-]*-[^-]*確保-在匹配行的第二次出現之前獲取值。
echo "echo home/JOHNSMITH-4991-common-task-list" | grep -oP '.*/\K[^-]*-[^-]*'
uj5u.com熱心網友回復:
這是一個使用cutbash 字串替換的簡單替代解決方案:
s='home/JOHNSMITH-4991-common-task-list'
cut -d- -f1-2 <<< "${s##*/}"
JOHNSMITH-4991
uj5u.com熱心網友回復:
您可以匹配直到第一次出現/,然后清除匹配緩沖區,\K然后重復字符類 1 次,中間有一個連字符,以至少選擇連字符前后的字符。
[^/]*/\K[A-Z0-9] -[A-Z0-9]
如果支持,請使用 gnu grep:
echo "echo home/JOHNSMITH-4991-common-task-list" | grep -oP '[^/]*/\K[A-Z0-9] -[A-Z0-9] '
輸出
JOHNSMITH-4991
Ifgnu awk是一個選項,使用相同的模式但有一個捕獲組:
echo "home/JOHNSMITH-4991-common-task-list" | awk 'match($0, /[^\/]*\/([A-Z0-9] -[A-Z0-9] )/, a) {print a[1]}'
如果所需的輸出始終是帶有連字符的字符類匹配的第一個匹配項:
echo "home/JOHNSMITH-4991-common-task-list" | awk -v FPAT="[A-Z0-9] -[A-Z0-9] " '$0=$1'
輸出
JOHNSMITH-4991
uj5u.com熱心網友回復:
假設:
- 字串中的斜線可能不止一個
- (在最后一個 fwd 斜杠之后)字串中有 2 個或更多連字符
- 所需的輸出在最后一個 fwd 斜杠和第二個連字符之間
使用引數替換的一種想法:
$ string='home/dir/JOHNSMITH-4991-common-task-list'
$ string1="${string##*/}"
$ typeset -p string1
declare -- string1="JOHNSMITH-4991-common-task-list"
$ string1="${string1%%-*}"
$ typeset -p string1
declare -- string1="JOHNSMITH"
$ string2="${string#*-}"
$ typeset -p string2
declare -- string2="4991-common-task-list"
$ string2="${string2%%-*}"
$ typeset -p string2
declare -- string2="4991"
$ newstring="${string1}-${string2}"
$ echo "${newstring}"
JOHNSMITH-4991
筆記:
typeset添加的命令僅用于顯示值的進展- 有點打字,但如果在
bash整體性能中這樣做很多次,與需要產生子流程的其他解決方案相比應該是好的 - 如果需要決議大量字串,最佳性能將來自一次將所有字串(通過檔案?)流式傳輸到其他解決方案之一(例如,處理所有字串的單個
awk呼叫將比運行集合更快字串通過bash回圈并執行所有這些引數替換)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/341794.html
