2015-10-15 114 views
3

我做了這個正則表達式,但它不工作。bash爲什麼我的正則表達式不工作?

我得到這個字符串: ( '/test/test/test/test-Test/TEST/test.sql'),

我的bash代碼:

if [[ ${arrayQuery[$i]} =~ ([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9-]+)\/([a-z0-9]+)\/([a-z0-9]+).([a-z0-9]+) ]]; then 
     queryName=$1 
     echo "test $queryName" 
fi 

它不是任何人都可以解釋我爲什麼這不起作用?

我在regex101.com上試了我的正則表達式,正則表達式在本網站上工作。

+1

它看起來對我來說,你只是在尋找小寫字母和數字,但你必須在本例中字符串大寫字母,所以它不應該匹配。 –

+0

您不需要在正則表達式中轉義'/'。 ''bash'不會像'sed'那樣用它作爲分隔符,例如',所以它們沒有特殊的含義。 – chepner

+0

我可以問你,爲什麼你使用這個正則表達式?你是否試圖將你的路徑分成它的dir組件? –

回答

0

如果您將A-Z(大寫字母)添加到所有字符集,它應該可以工作。

2
  • 你需要躲避點,否則匹配任何字符

  • 你的榜樣字符串包含大寫字母,但你的正則表達式只接受小寫字母

(編輯:無報價需要)

0

您可以使用[[:alnum:]]作爲(正確)類[a-zA-Z0-9]的捷徑,以簡化您的正則表達式,而fixi它。即使是簡單的將是使用參數來縮短:

x='[[:alnum:]]+' 
# Or, if you prefer 
# x='[a-zA-Z0-9]+' 
if [[ ${arrayQuery[$i]} =~ ($x)/($x)/($x)/($x)/($x)/($x)\.($x) ]]; then 
    queryName=$1 
    echo "test $queryName" 
fi 

也有使正則表達式的選項匹配不區分大小寫的,這樣可以讓你使用當前的正則表達式(有一些小的修正) :

shopt -s nocasematch 
if [[ ${arrayQuery[$i]} =~ ([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9-]+)/([a-z0-9]+)/([a-z0-9]+)\.([a-z0-9]+) ]]; then 
    queryName=$1 
    echo "test $queryName" 
fi 
shopt -u nocasematch # Turn it off again 
+1

你錯過了那個「 - 」字符,需要匹配「test-Test」部分 –

+1

好點。不知道這應該在每個組件中,還是隻在包含用戶輸入中的組件中。目前還不清楚正則表達式應該是什麼。 – chepner

+0

你還錯過了字符串'/test/test/test/test-Test/TEST/test.sql'的第一個字符'/',因爲你的正則表達式以「([a-z0-9] +)開始」 –

1

您的例子並不在regex101與你有幾個原因提供的字符串工作:

  1. 你的字符串以「/」開頭,但您正則表達式用([A-Z0-9開始] +)
  2. 你的字符串包含大寫字母,你卻不使用[AZ]在您的正則表達式
  3. 你的字符串包含一個「 - 」但是你的正則表達式不分析它,嘗試添加\ -
  4. 你沒有逃脫該點用'\。'替換,默認爲'。'。意味着所有的字符

這個正則表達式會做的伎倆(link to regex101):

\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+ 

我想這個字符串代表您的硬盤驅動器中的SQL文件,這個正則表達式可以簡化爲:

(\/[a-zA-Z0-9\-]+)+\.sql 

並且不依賴於目錄樹中有多少個文件夾。

+0

因此我將代碼更改爲:\t'code echo「$ {arrayQuery [$ i]}」 \t if [[$ {arrayQuery [$ i]} =〜(\ /([a-zA-Z0-9 \ - ] +)\ /([A-ZA-Z0-9 \ - ] +)\ /([A-ZA-Z0-9 \ - ] +)\ /([A-ZA-Z0-9 \ - ] +)\ /([A-ZA-Z0-9 \ - ] +)\ /([A-ZA-Z0-9 \ - ] +)\([A-ZA-Z0-9 \ - ] + ))]]];然後 \t \t queryName = $ 1 \t \t回聲「測試$ queryName」 \t fi' – kaspertje100

+0

它不進入if語句現在(在控制檯中我看到它打印測試),但它不打印$ queryName因爲$ 1變量是空。我不明白爲什麼1美元是空的可以向我解釋這一點嗎? – kaspertje100

+0

Neverm ind修復它。我使用$ {BASH_REMATCH [1]}「來打印結果。在$ bash中不存在$ 1。 – kaspertje100

0

從您的評論看來,你似乎想將路徑拆分成其組件。最好的選擇,在Bash中,就是用這樣的:

mypath=/testa/testb/testc/test-Testd/TESTe/test.sql 
IFS=/ read -r -d '' -a components < <(printf '%s\0' "$mypath") 

像這樣,你就會有一個陣列components將包含路徑的每個組件:

gniourf$ declare -p components 
declare -a components='([0]="" [1]="testa" [2]="testb" [3]="testc" [4]="test-Testd" [5]="TESTe" [6]="test.sql")' 

你不」 t需要(並且不希望)爲此使用正則表達式。

也看到了這個問題:How do I split a string on a delimiter in Bash?

相關問題