Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash-将下划线替换为空格,前导/尾随下划线除外_Bash_Shell_Sed - Fatal编程技术网

Bash-将下划线替换为空格,前导/尾随下划线除外

Bash-将下划线替换为空格,前导/尾随下划线除外,bash,shell,sed,Bash,Shell,Sed,我希望单词之间的下划线替换为空格,并保留前导和尾随下划线。例如: __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_REM

我希望单词之间的下划线替换为空格,并保留前导和尾随下划线。例如:

__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+xbanana
,我们开始:

$ ./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动词


上面的正则表达式将匹配所有的
,除了前面和后面的正则表达式。

另一种纯粹的Bash可能性,它不使用正则表达式,而是使用扩展的globs,非常简单:

#!/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_下划线
将包含不带前导和尾随下划线的字符串。从这里,很容易得到前导下划线和尾随下划线的数量,在
中用空格替换下划线,并将所有内容放回一起。

另一个Perl答案:

perl -pe 's/(?<=[^\W_])(_+)(?=[^\W_])/ " " x length($1) /ge' <<END
__hello_world_a_b___
hello___world
END

也就是说:一系列下划线,前面是除下划线外的单词字符,后面是除下划线外的单词字符。

如果您有GNU awk,可以使用

awk '{match($0,"^(_*)(.*[^_])(_*)$",arr); print arr[1] gensub("_"," ","g",arr[2]) arr[3]}'

-1表示“具有数组和函数”。如果这是一个合法的要求,你应该解释它;如果没有,你应该删除它(并简单地要求最好的方法)。PCRE动词都有点微妙,并且没有被广泛理解。因此,这是主观的,但我认为最好编写类似于
perl-pe'的代码,如果(m/^(*)([^.[^.].[^\n])(*\n?)\z/{my($leading,$words,$trailing)=($1,$2,$3);$words=~s/\ug;$”$leading$words$trailing“}
@ruakh,这是eckes已经提出的。但他删除了他的答案。如果您理解上面的PCRE动词,就不需要像上面那样编写长代码。
__hello world a b___
hello   world
awk '{match($0,"^(_*)(.*[^_])(_*)$",arr); print arr[1] gensub("_"," ","g",arr[2]) arr[3]}'