我想要用空格替换单词之间的下划线,单独留下前导和尾部下划线。例如: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