簡體   English   中英

使用grep進行正則表達式格式化

[英]Regex formatting using grep

我正在為我的應用程序解析mp3文件的IDv3標簽,我正在使用id3v2 例如,要獲取mp3文件的專輯名稱,命令是

id3v2 -R sample.mp3 | grep "TALB"

哪個輸出

TALB: Album Name

但是,我想只得到TALB的值,而不是整行,所以我將它傳遞給sed ,如下所示

id3v2 -R sample.mp3 | grep "TALB" | sed 's/TALB: //'

哪個輸出

Album Name

所以,這是我的問題:

  1. 只有通過grep才能實現上述結果。 如果是這樣,我該怎么辦?
  2. 即使我得到了我想要的結果,但是當我在尋找像TCON這樣的其他標簽時,它會返回example.com (255) ,其中我只需要example.com 那么,我如何在這種類型的grep編寫正則表達式?

您可以將Perl樣式的正則表達式與-P標志一起使用:

grep -Po '(?<=TALB: ).*'

例如:

$ echo "TALB: Album Name" | grep -Po '(?<=TALB: ).*'
Album Name

(?<=TALB: )是一個零寬度的后視斷言 .*是你想要匹配的其他東西的模式 - 在第一種情況下,一切。 如果您只想匹配標記字符串后面的特定字符串,就像在第二個問題中那樣,那么您可以更改它以適合您的特定數據。

這是一個更動態的方法,只使用沒有外部的bash ,您可以使用它來將所有/所需的標簽讀取到同名的變量中以供進一步使用。 這樣更快,為您提供所需的所有標簽,無需進一步的成本/代碼。

另一個好處是它是可移植的( <<<需要bash 2.05${foo,,}需要bash 4但可以輕松刪除,其余的是POSIX)。 grep -P雖然非常方便,但在OS X上不再可用,因此如果主要平台之間的可移植性受到關注,則不太適合腳本。

#!/bin/bash

# read line-wise from stdin using colon ':' as additional delimiter.
# what comes before ':' gets stored in $key, what comes after in $value
while IFS=' \t:' read -r key value; do
    # check if the value of $key is a tag that we are interested in
    case ${key} in
        TALB|TCON|TFOO) ;; # $key is one of TALB, TCON or TFOO. let's continue
        *) continue     ;; # otherwise, ignore line and read next line
    esac

    # store $value in the variable named $key, e.g. if
    #   $key == "TCON" and $value == "Album Name"
    # this would create $tcon == "Album Name"
    # (${key,,} converts $key to lowercase during the process)
    read -r "${key,,}" <<< "${value}"
done <<__DATA__
TALB: Album Name
TCON: example.com (255)
TFOO: tfoo
TBAR: tbar
__DATA__

echo "TALB: $talb"
echo "TCON: ${tcon% (255)}"  # strip the trailing " (255)" from $tcon
echo "TFOO: $tfoo"
echo "TBAR: $tbar"

$ ./t.sh
TALB: Album Name
TCON: example.com
TFOO: tfoo
TBAR:

${foo,,}bash 4概念將$foo擴展$foo小寫以避免使用大寫變量名,但是如果你沒有bash 4你可以刪除它並使用大寫名稱或使用tr將它們轉換為小寫。

while read line -idiom 在這里得到了很好的解釋。

而不是我用來模擬id3v2的輸出的heredoc ,你將使用進程替換 “將id3v2的輸出傳遞到循環中”,例如

while [...]; do
    [...]
done < <(id3v2 -R Idhayam.mp3)

我認為這對awk是個好工作:

id3v2 -R Idhayam.mp3 | awk -F': ' '/^TALB/ {print $2}'

將在冒號后打印部分。 -F開關用於指定分隔符,在本例中為分隔符,后跟空格。 如果TALB的開頭找到TALB ,則打印第二列。

“TALB”部分可以放入變量中,例如:

id3v2 -R Idhayam.mp3 | awk -F': ' -v i="TALB" '"/^"i"/" {print $2}'

如果您只想要括號前面的部分,您可以這樣做:

awk -F': ' -v i="TCON" '"/^"i"/" { split($2,a,"("); print a[1] }'

這使用split來創建一個數組a ,它保存第二列的內容, (作為分隔符。然后它打印該數組的第一個元素。


如果您更喜歡使用sed那么也不需要grep 您可以使用這樣的正則表達式:

sed -n 's/^TCON: \([^(]*\).*/\1/p'

這僅打印相關部分(以“TCON”開頭的行的( )之前的部分。將-n傳遞給sed意味着它默認不打印每一行。

  • ^TCON匹配以“TCON:”開頭的行
  • \\( \\)捕獲這些括號之間的東西(需要斜杠作為轉義字符)
  • [^(]不是“(”的字符)
  • *零個或多個
  • .*吞下剩下的線

整行代替\\1 ,它指的是之前捕獲的部分。 p表示打印。

暫無
暫無

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

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