2015-02-24 53 views
1

iamnewbie:這段代碼效率不高,但它應該提取子串,問題出在最後一個echo語句上,需要一些見解。bash中的子串提取

function regex { 


    #this function gives the regular expression needed 



    echo -n \' 

    for ((i = 1 ; i <= $1 ; i++)) 
     do 
      echo -n . 
     done 

    echo -n '\(' 

    for ((i = 1 ; i <= $2 ; i++)) 
     do 
      echo -n . 
     done 

    echo -n '\)' 
    echo -n \' 

    } 
    # regex function ends 


     echo "Enter the string:" 

     read stg 
     #variable stg holds the string entered 

     if [ -z "$stg" ] ; then 

      echo "Null string" 

     exit 

     else 

      echo "Length of the $stg is:" 

      z=`expr "$stg" : '.*' ` 

      #variable z holds the length of given string 

      echo $z 

     fi 

     echo "Enter the number of trailing characters to be extracted from $stg:" 

     read n 

     m=`expr $z - $n ` 
     #variable m holds an integer value which is equal to total length - length of characters to be extracted 

     x=$(regex $m $n) 

     echo ` expr "$stg" : "$x" ` 
     #the echo statement(above) is just printing a newline!! But not the result 

我打算使用此代碼做的是,如果我輸入「賽車」,給「3」,它應該顯示「汽車」,這是最後三個字符。而不是顯示「汽車」它只是打印換行符。請更正此代碼,而不是提供更好的代碼。

+0

的問題是你的輸出包含一個尾隨的換行符?這就是'echo'所做的。試試'printf%s $(expr ...)'? – 2015-02-24 20:15:37

+0

@EtanReisner:正如書面所示,回聲有點沒有意義,除了規範化空白。雖然可能不是所提到的問題。我認爲問題是手動插入到$ regex中的撇號。對於那個綜合徵,真的需要有一個經典的答案。 – rici 2015-02-24 20:17:12

+0

但我已經在正則表達式函數中使用了echo -n – 2015-02-24 20:18:24

回答

2

你雖然沒有要求一個更好的解決方案,這是值得一提:

$ n=3 
$ stg=racecar 
$ echo "${stg: -n}" 
car 

注意空間後${stg: -n}:要求。如果沒有空格,參數擴展是默認值擴展而不是子字符串擴展。有了空間,這是一個子字符擴展; -n被解釋爲算術表達式(這意味着n被解釋爲$n),並且由於結果是負數,因此它指定從結尾開始子字符的字符數。有關詳細信息,請參閱Bash manual


您的解決方案是基於評估的等價物:

expr "$stg" : '......\(...\)' 

用點適當數量。理解上面的bash語法實際上意味着什麼很重要。它調用命令expr,並向它傳遞三個參數:

ARG 1::

ARG 3::可變stg

ARG 2的內容......\(...\)

注意,沒有引號可見。這是因爲引號是bash 語法的一部分,而不是參數值的一部分。

如果stg的值有足夠的字符,則上述expr調用的結果將打印出stg`的值的第7,8,9個字符。否則,它將打印一個空白行,並失敗。

但是,這不是你在做什麼。要創建的正則表達式:

'......\(...\)' 

這有單引號。由於單引號在正則表達式中不是特殊字符,因此它們自己匹配;換句話說,該模式將匹配以單引號開頭的字符串,後跟九個任意字符,後跟另一個單引號。如果字符串匹配,它將在第二個單引號之前打印三個字符。

當然,因爲你做的正則表達式有在目標字符串中的每個字符.,它不會匹配的目標,即使目標開始,並開始一個單引號,因爲會有太多正則表達式中的點與之匹配。

如果你不把單引號放到正則表達式中,那麼你的程序就可以工作,但是我必須說有幾次我見過這樣一個強烈的迂迴實現的子字符串函數。如果你沒有試圖贏得混淆的bash比賽(由於大多數生產bash代碼被大自然混淆而成爲一個艱難的挑戰),我建議你使用普通的bash特性,而不是試圖用regexen做所有事情。

其中之一是語法來確定一個字符串的長度:

$ stg=racecar 
$ echo ${#stg} 
7 

(儘管,如開頭所示,你實際上並不甚至需要一個)

+0

我刪除了引號和程序工作!感謝您的耐心和見解 – 2015-02-25 04:49:23

1

關於什麼:

$ n=3 
$ string="racecar" 
$ [[ "$string" =~ (.{$n})$ ]] 
$ echo ${BASH_REMATCH[1]} 
car 

這看起來最後n字符在該行的末尾。在一個腳本中:

#!/bin/bash 

read -p "Enter a string: " string 
read -p "Enter the number of characters you want from the end: " n 
[[ "$string" =~ (.{$n})$ ]] 
echo "These are the last $n characters: ${BASH_REMATCH[1]}" 

你可能想添加一些更多的錯誤處理,但這會做到這一點。

+0

BASH_REMATCH是如何工作的? – 2015-02-25 04:54:53

+0

BASH_REMATCH是一個由bash設置的變量,在做正則表達式時(如[[... =〜...]])有或沒有組捕獲,就像上面的'(。{$ n})'一樣。括號「捕捉」一個組,其中第一個在索引1中,第二個在索引2中,等等。在這種情況下,你可能只需要使用'$ {BASH_REMATCH [0]}',這將返回整個匹配,這必須只有三個字符,所以你可能甚至不需要分組/捕獲。這可能是評論中太多的解釋。 – zerodiff 2015-02-25 15:20:15

1

我不確定你需要循環執行此任務。我寫了一些例子來從用戶那裏得到兩個參數,並根據它來剪切這個單詞。

#!/bin/bash 
read -p "Enter some word? " -e stg 
#variable stg holds the string entered 
if [ -z "$stg" ] ; then 
    echo "Null string" 
    exit 1 
fi 

read -p "Enter some number to set word length? " -e cutNumber 
# check that cutNumber is a number 
if ! [ "$cutNumber" -eq "$cutNumber" ]; then 
    echo "Not a number!" 
    exit 1 
fi 
echo "Cut first n characters:" 
echo ${stg:$cutNumber} 
echo 
echo "Show first n characters:" 
echo ${stg:0:$cutNumber} 

echo "Alternative get last n characters:" 
echo -n "$stg" | tail -c $cutNumber 
echo 

例子:

Enter some word? TheRaceCar 
Enter some number to set word length? 7 
Cut first n characters: 
Car 

Show first n characters: 
TheRace 
Alternative get last n characters: 
RaceCar 
+0

效果很好,你能告訴我關於如果! [「$ cutNumber」-eq「$ cutNumber」] – 2015-02-25 05:03:08

+0

-eq是一個整數比較。它意味着等於。它僅適用於數字,因此它是一種簡單的方法來檢查是否有數字。 [TLDP](http://tldp.org/LDP/abs/html/comparison-ops.html)。 [! EXPR]如果EXPR爲假,則爲真。 [Bash初學者指南](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html) – idobr 2015-02-25 08:29:12