在bash
脚本中,如何从字符串中删除单词,该单词将存储在变量中。
FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"
答案1
使用bash
子字符串替换(从 ksh93 复制):
FOO=${FOO//"$WORDTOREMOVE"/}
将//
所有出现的子字符串 () 替换为和$WORDTOREMOVE
之间的内容。在这种情况下什么也没有。/
}
请注意周围的引号,$WORDTOREMOVE
以确保内容被视为固定字符串而不是模式。
当替换为空时,/
也可以省略:${FOO//"$WORDTOREMOVE"}
。
有关在 bash 中使用字符串的方法和其他方法的信息,请参阅 部分10.1.操作字符串的高级 Bash 脚本指南。
答案2
尝试:
$ printf '%s\n' "${FOO//"$WORDTOREMOVE"/}"
CATS DOGS FISH
这也适用于ksh93
(它来自哪里)mksh
和zsh
。
正面:
FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"
remove_word() (
set -f
IFS=' '
s=$1
w=$2
set -- $1
for arg do
shift
[ "$arg" = "$w" ] && continue
set -- "$@" "$arg"
done
printf '%s\n' "$*"
)
remove_word "$FOO" "$WORDTOREMOVE"
它假设您的单词是用空格分隔的,并且具有删除前后空格的副作用"$WORDTOREMOVE"
。
答案3
您可以使用sed
像这样:
echo $FOO | sed s/"$WORDTOREMOVE"//
答案4
删除一个单词从表示以空格分隔的单词列表的字符串中获取数据并不那么容易,因为您需要决定如何处理每一侧的空格。
即使在单词之间始终有一个空格的驯服表示中,您也需要区分几种不同的情况:
- 中间的单词:
foo MICE bar
->foo bar
:单词及其之前的空格和之后的空格替换为单个空格。${var/+( )MICE+( )/ }
- 开头的单词:
MICE foo bar
->foo bar
:单词和后面的空格替换为空:${var/MICE+( )}
- 末尾的单词:
foo bar MICE
->foo bar
:单词和前面的空格替换为空:${var/+( )MICE}
。 - 然后会出现一个问题,即单词 where 的多次连续出现
${var// MICE / }
将无法正常工作,foo MICE MICE bar
因为第一个替换会占用第二个 MICE 之前的空间。
(上面使用${var/pattern/replacement}
ksh93 中的运算符)。
不过,如果您在进行替换之前在开头和结尾添加一个空格并在之后删除它们,那么它会变得更容易,因为这样您就可以用一个替换运算符覆盖所有基础:
var='MICE foo MICE MICE bar MICE'
word=MICE
var=" $var "
var=${var//+(+([[:space:]])"$word")+([[:space:]])/ }
var=${var# } var=${var% }
您需要事先shopt -s extglob
在 bash 或set -o kshglob
zsh 中支持+([[:space:]])
ksh88 运算符来匹配 1 个或多个空白字符。
或者使用zsh
's 自己的extendedglob
s ( set -o extendedglob
),其中 ksh+(x)
变为x##
:
var=${var//([[:space:]]##$word)##[[:space:]]##/ }
甚至可以恢复单词 with 之前或之后的间距(在zsh
; ksh93 中会有等效的内容,而不是 bash):
var='MICE foo MICE MICE bar MICE'
word=MICE
set -o extendedglob
var=" $var "
var=${var//(#b)([[:space:]]##$word)##([[:space:]]##)/$match[2]}
var=${var# } var=${var% }
如果您有一个实际的变量,而不是包含列表表示的标量变量列表(数组)变量,如:
var=(MICE foo MICE MICE bar MICE)
然后问题就简化为从数组中删除特定元素,这对于具有适当数组变量的 shell 来说变得微不足道,例如zsh
(该var=(foo bar)
语法的来源):
var=( ${var:#$word} )