[英]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
所以,這是我的問題:
grep
才能實現上述結果。 如果是這樣,我該怎么辦? 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.