2016-11-23 113 views
4

我有這個例子的字符串:純擊替換捕獲組

test_string="13A6" 

這字符/數字可以是從0到9和從A到F.

我想要這個輸出:

1 3 A 6 

我有這樣的工作:

result=$(echo ${test_string} | sed 's/./& /g') 

我想這樣做沒有sed的......我有另一種解決辦法,我不喜歡太...髒:S

[[ ${test_string} =~ ^([0-9A-F])([0-9A-F])([0-9A-F])([0-9A-F]) ]] && result="${BASH_REMATCH[1]} ${BASH_REMATCH[2]} ${BASH_REMATCH[3]} ${BASH_REMATCH[4]}" 

我想,如果可能的話,使用純慶典與語法result=${variable//pattern/replacement},但不知道如何在sed中使用「&」來引用這種純粹的bash語法中的匹配字符本身。任何bash大師? :)

+1

帶循環:http://stackoverflow.com/a/32545111/3776858 – Cyrus

回答

3

這個怎麼樣(被稱爲無外部工具):

str="13A6" 
[[ $str =~ ${str//?/(.)} ]] 
printf '%s\n' "${BASH_REMATCH[*]:1}" 

結果(無空格):

"1 3 A 6" 

或者,如果你需要使用一個不同的分隔符:

[[ $str =~ ${str//?/(.)} ]] 
(IFS=$'\n'; printf "%s\n" "${BASH_REMATCH[*]:1}") 

或者,在函數上,IFS可以是本地的功能:

divide(){ 
    [[ $1 =~ ${1//?/(.)} ]] 
    local IFS=${2:-' '} 
    printf '%s\n' "${BASH_REMATCH[*]:1}" 
} 

divide "13A6" "-"   # will output 1-3-A-6 in this example. 

這是這樣的:

  ${str//?/(.)}    # Replace each character with "(.)". 
[[ $str =~    ]]   # Match the regex "(.)(.)(.) … …" 
             # capturing each character matched 
             # in the array "${BASH_REMATCH[@]}" 

printf '%s\n' "${BASH_REMATCH[*]:1}" # Forget array index 0 and 
             # convert the array to one string 
             # using the first character 
             # of "$IFS" as separator 
             # (no trailing separator). 

感謝@chepner的建議在陣列中更改@*。這避免了使用時間數組或位置參數的需要。

+2

這是非常好的。不過,您不需要覆蓋位置參數; 'echo'\「$ {BASH_REMATCH [*]:1} \」「'也可以工作,或者您可以使用捕獲組來填充數組:'arr =(」$ {BASH_REMATCH [@]:1}「) '。 – chepner

0

我不知道,如果你想它是爲純:

test_string="13A6" 
length=$(expr length "$test_string") 
s="" 
for ((i=1;i<=${length};i++)) 
do 
    c=$(expr substr "${test_string}" $i 1) 
    s=${s}" "$c 
done 
echo $s 

RES:

1 3 A 6 

或者最純淨的(無外部程序)與chepner的幫助。

test_string="13A6" 
s="" 
for ((i=0;i<${#test_string};i++)) 
do 
    s=${s}" "${test_string:i:1} 
done 
echo $s 
+1

沒有理由在這裏使用'expr';你可以用'$ {#test_string}'得到一個字符串的長度,你可以用'$ {test_string:i:1}'從一個字符串中獲得單個字符。 – chepner