我想要用空格替換單詞之間的下劃線,單獨留下前導和尾部下劃線。例如:Bash - 用空格替換下劃線,除了前導/後綴
__hello_world_a_b___
hello___world
應該成爲
__hello world a b___
hello world
我想要用空格替換單詞之間的下劃線,單獨留下前導和尾部下劃線。例如:Bash - 用空格替換下劃線,除了前導/後綴
__hello_world_a_b___
hello___world
應該成爲
__hello world a b___
hello world
使用bash其正則表達式的支持:
string='__hello_world_a_b___'
[[ $string =~ ^(_*)(.*[^_])(_*)$ ]]
echo "${BASH_REMATCH[1]}${BASH_REMATCH[2]//_/ }${BASH_REMATCH[3]}"
要檢查它的工作原理,讓我們做一個腳本,將採取字符串作爲參數:
#!/bin/bash
string=$1
[[ $string =~ ^(_*)(.*[^_])(_*)$ ]]
echo "${BASH_REMATCH[1]}${BASH_REMATCH[2]//_/ }${BASH_REMATCH[3]}"
調用此腳本banana
,chmod +x banana
,讓我們去:
$ ./banana '__hello_world_a_b___'
__hello world a b___
$ ./banana '__hello_world_a_b'
__hello world a b
$ ./banana 'hello_world_a_b___'
hello world a b___
$ ./banana 'hello_world_a_b'
hello world a b
$ ./banana '___'
$ # the previous output is empty
$ ./banana $'___hello_world_with\na_newline___'
___hello world with
a newline___
$ ./banana 'hello___world'
hello world
你可以簡單地使用下面的Perl命令,該命令使用PCRE動詞(*SKIP)(*F)
。
$ echo "hello___world" | perl -pe 's/(?:^_+|_+$)(*SKIP)(*F)|_/ /g'
hello world
$ echo "__hello_world_a_b___" | perl -pe 's/(?:^_+|_+$)(*SKIP)(*F)|_/ /g'
__hello world a b___
上述正則表達式可以匹配所有的_
,除了前導和尾隨之外。
PCRE動詞都有點微妙,並沒有很廣泛的理解。所以,這是主觀的,但是我認爲最好寫一些類似'perl -pe'的if(m/^(_ *)([^ _]。* [^ _ \ n])(_ * \ n?) \ z /){my($ leading,$ words,$ trailing)=($ 1,$ 2,$ 3); $ words =〜s/_// g; $ _ =「$ leading $ words $ trailing」}「'。 – ruakh 2014-11-02 01:44:55
@ruakh它已經被eckes建議。但他刪除了他的答案。如果你理解上面的PCRE動詞,你不需要像上面那樣寫一個長的代碼。 – 2014-11-02 01:51:17
不使用正則表達式,但延長的水珠,在一個非常行人路的另一種純擊可能性:
#!/bin/bash
shopt -s extglob
string=$1
wo_leading=${string##+(_)}
wo_underscore=${wo_leading%%+(_)}
printf -v leading '%*s' "$((${#string}-${#wo_leading}))"
printf -v trailing '%*s' "$((${#wo_leading}-${#wo_underscore}))"
echo "${leading// /_}${wo_underscore//_/ }${trailing// /_}"
變量wo_leading
將包含字符串沒有前導下劃線,並且變量wo_underscore
將包含沒有開頭和尾部下劃線的字符串。從這裏可以很容易地得到前後的下劃線數字,用wo_underscore
中的空格替換下劃線,並將所有內容放在一起。
另一個Perl的答案:
perl -pe 's/(?<=[^\W_])(_+)(?=[^\W_])/ " " x length($1) /ge' <<END
__hello_world_a_b___
hello___world
END
__hello world a b___
hello world
即:由一個字符,除了下劃線單詞字符之前,並且通過字符後跟下劃線的序列是一個字字符除了下劃線。
如果你有GNU AWK,你可以用
awk '{match($0,"^(_*)(.*[^_])(_*)$",arr); print arr[1] gensub("_"," ","g",arr[2]) arr[3]}'
-1做它 「與陣列和功能」。如果這是一個合法的要求,你應該解釋它;如果沒有,你應該刪除它(並且只是要求最好的方法)。 – ruakh 2014-11-02 01:30:34