Bash

使用正則表達式查找參數中給出的副檔名的文件

  • November 17, 2016

假設一個有以下命令

search /home/user proc .h .c .txt ...

我正在使用find命令建構一個腳本,以獲取所有以給定名稱開頭並以給定副檔名之一結尾的文件。

我已經設法使用循環來建構它:

directory=$1
fileName=$2
fileExtensions=""

for arg in "$@"
do
   #skipping first and second argument
    if [ $arg = $1 -o $arg = $2 ]; then 
       continue;
   fi
   fileExtensions+="${arg//.}\|"
done
#removing the last '|', otherwise regex parser error occurs
fileExtensions=${fileExtensions::-1}

find $directory -name "$fileName*" -regex ".*\.\($fileExtensions)"

有沒有更優雅的方法可以使用正則表達式來實現這一點?

感謝您的幫助!

該腳本可以簡化為:

directory=$1
fileName=$2
shift 2

a="$*"    b="${*#.}"
(( ${#a} - ${#b} - $# )) && echo "some extension(s) is(are) missing a leading dot." >&2

fileExtensions="$(IFS=\|; echo "${*#.}")"

find "$directory" -name "$fileName*" -regextype posix-egrep -regex ".*\.($fileExtensions)$"

預設情況下,find 接受 emacs 類型的正則表達式,要使用該類型需要幾個反斜杠,例如\|. 這可以通過使用不同類型的正則表達式來避免(如上所述)。

Where${*#.}刪除前導點(如果存在)並將所有剩餘的“位置參數”與 IFS 的第一個字元的值連接起來,該值設置為|用於執行子 shell。

只需一個變數賦值和一個“參數擴展”,這就是所有需要的。


EDIT用於檢查參數列表中提供的所有擴展是否都以點開頭

(( ${#a} - ${#b} - $# ))

連接的所有參數的字元數 ( ${#a}) ( a=$*)

應等於連接的所有參數

的字元數 ( ${#b})(刪除一個前導點) ( b=${*#.})

加上

參數的數量 ( $#)。

${#a} == ${#b} + $#

當且僅當所有參數都有一個前導點。

作為算術測試:

((  ${#a} - (${#b} + $#)  ))

或者還有:

((  ${#a} - ${#b} - $#  )) && echo "missing leading dot(s)."

編輯二

命令行參數中給出的擴展列表在此處處理:

fileExtensions="$(IFS=\|; echo "${*#.}")"

這是它的工作原理,由內而外:

$*   # This generates a string of all positional arguments using IFS.

來自LESS=+'/Special Parameters' man bash

那是, ” $ *" is equivalent to " $ 1c$2c…",其中 c 是 IFS 變數值的第一個字元。

然後我們使用“參數擴展”來切割每個位置參數的前面:

${parameter#word}     # used as ${*# } above.

來自LESS=+/'parameter#word' man bash

如果參數是@或*,模式移除操作將依次應用於每個位置參數,擴展是結果列表。

word一個擴展中的 dot 設置為 dot .,從而刪除了所有位置參數前面的點。

由於此時的 IFS 以一個|字元開頭,該字元用於建構一個字元串,該字元串|作為參數列表的分隔符,該參數列表在前面帶有一個點。

該字元串被提供給命令 echo 以使其列印。

但是在執行 echo 命令之前,變數$IFS被設置為 a |

它包含在命令執行$(…)中(創建一個子 shell,它在結束時會忘記對 IFS 的更改)。

然後我們將字元串分配給一個變數:

fileExtensions="$(IFS=\|; echo "${*#.}")"

簡而言之:轉換.c .h .txtc|h|txt.

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