String 如何修剪Bash变量中的空白?
我有一个包含以下代码的shell脚本:String 如何修剪Bash变量中的空白?,string,bash,variables,trim,String,Bash,Variables,Trim,我有一个包含以下代码的shell脚本: var=`hg st -R "$path"` if [ -n "$var" ]; then echo $var fi 但是条件代码总是执行,因为hgst总是打印至少一个换行符 有没有一种简单的方法可以去除$var中的空白(比如trim()) 或 有没有一个标准的方法来处理这个问题 我可以使用或,但我想有一个更优雅的解决方案来解决这个问题。我一直使用sed var=`hg st -R "$path" | sed -e 's/ *$//
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
但是条件代码总是执行,因为hgst
总是打印至少一个换行符
- 有没有一种简单的方法可以去除
中的空白(比如$var
)trim()
- 有没有一个标准的方法来处理这个问题
我可以使用或,但我想有一个更优雅的解决方案来解决这个问题。我一直使用sed
var=`hg st -R "$path" | sed -e 's/ *$//'`
如果有一个更优雅的解决方案,我希望有人发布。Bash有一个名为参数扩展的功能,除其他外,它允许基于所谓的模式进行字符串替换(模式类似于正则表达式,但有根本的区别和限制)。 [flussence的原始行:Bash有正则表达式,但它们隐藏得很好:] 下面演示如何从变量值中删除所有空白(甚至从内部)
$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef
您可以使用
tr
删除换行符:
var=`hg st -R "$path" | tr -d '\n'`
if [ -n $var ]; then
echo $var
done
FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12
我见过脚本只是使用变量赋值来完成任务:
$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar
空白会自动合并和修剪。必须注意shell元字符(潜在的注入风险)
我还建议在shell条件中始终双重引用变量替换:
if [ -n "$var" ]; then
因为变量中的a-o或其他内容可能会修改测试参数。去掉一个前导空格和一个尾随空格
例如:
test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"
test4="$(trim " two leading")"
test5="$(trim "two trailing ")"
test6="$(trim " two leading and two trailing ")"
echo "'$test4', '$test5', '$test6'"
输出:
'one leading', 'one trailing', 'one leading and one trailing'
'two leading', 'two trailing', 'two leading and two trailing'
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
wordA wordB wordC
wordAA
>four spaces before<
>one space before<
>here is
something<
test
去掉所有前导和尾随空格
例如:
test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"
test4="$(trim " two leading")"
test5="$(trim "two trailing ")"
test6="$(trim " two leading and two trailing ")"
echo "'$test4', '$test5', '$test6'"
输出:
'one leading', 'one trailing', 'one leading and one trailing'
'two leading', 'two trailing', 'two leading and two trailing'
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
wordA wordB wordC
wordAA
>four spaces before<
>one space before<
>here is
something<
test
使用AWK:
echo $var | awk '{gsub(/^ +| +$/,"")}1'
你可以使用老式的
tr
。例如,这将返回git存储库中已修改文件的数量,即删除的空白
MYVAR=`git ls-files -m|wc -l|tr -d ' '`
启用Bash的扩展模式匹配功能(
shopt-s extglob
)后,您可以使用:
{trimmed##*()}
删除任意数量的前导空格。将空格删除为一个空格:
(text) | fmt -su
让我们定义一个包含前导、尾随和中间空格的变量:
FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16
FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"
if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then
test=${BASH_REMATCH[1]}
fi
如何删除所有空白(在
tr
中用[:space:][/code>表示):
如何仅删除前导空格:
FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15
FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15
如何仅删除尾随空格:
FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15
FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15
如何删除前导空格和尾随空格--链接sed
s:
FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14
或者,如果您的bash支持它,您可以用sed替换echo-e“${FOO}”sed…
有一种解决方案只使用称为通配符的Bash内置项:
以下是包装在函数中的相同内容:
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "$var"
}
trim() {
# Determine if 'extglob' is currently on.
local extglobWasOff=1
shopt extglob >/dev/null && extglobWasOff=0
(( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
# Trim leading and trailing whitespace
local var=$1
var=${var##+([[:space:]])}
var=${var%%+([[:space:]])}
(( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
echo -n "$var" # Output trimmed string.
}
以引号形式传递要修剪的字符串。e、 g:
trim " abc "
这个解决方案的一个优点是它可以与任何兼容POSIX的shell一起工作
参考文献
- ()
赋值忽略前导和尾随空格,因此可用于修剪:
$ var=`echo ' hello'`; echo $var
hello
当IFS
变量设置为其他变量时,我需要从脚本中删除空白。依靠我,我成功了:
# trim() { echo $1; } # This doesn't seem to work, as it's affected by IFS
trim() { echo "$1" | perl -p -e 's/^\s+|\s+$//g'; }
strings="after --> , <-- before, <-- both --> "
OLD_IFS=$IFS
IFS=","
for str in ${strings}; do
str=$(trim "${str}")
echo "str= '${str}'"
done
IFS=$OLD_IFS
#trim(){echo$1;}#这似乎不起作用,因为它受IFS的影响
trim()
strings=“after-->,这里有一个trim()函数,用于修剪和规范化空白
#!/bin/bash
function trim {
echo $*
}
echo "'$(trim " one two three ")'"
# 'one two three'
和另一个使用正则表达式的变体
#!/bin/bash
function trim {
local trimmed="$@"
if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
then
trimmed=${BASH_REMATCH[1]}
fi
echo "$trimmed"
}
echo "'$(trim " one two three ")'"
# 'one two three'
从上的Bash指南部分
在参数扩展中使用extglob
#Turn on extended globbing
shopt -s extglob
#Trim leading and trailing whitespace from a variable
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}
#Turn off extended globbing
shopt -u extglob
以下是包装在函数中的相同功能(注意:需要引用传递给函数的输入字符串):
用法:
string=" abc def ghi ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");
echo "$trimmed";
mystring=" here is
something "
mystring=$(trim "$mystring")
echo ">$mystring<"
如果我们将函数改为在子shell中执行,我们就不必担心检查extglob的当前shell选项,我们可以在不影响当前shell的情况下设置它。这大大简化了函数。我还“就地”更新了位置参数,所以我甚至不需要局部变量
trim() {
shopt -s extglob
set -- "${1##+([[:space:]])}"
printf "%s" "${1%%+([[:space:]])}"
}
因此:
$s=$”\t\n\r\t oo
$shopt-u extglob
$shopt extglob
外接球
$printf“>%q这不存在不需要的全局搜索问题,而且内部空白未修改(假设$IFS
设置为默认值,即'\t\n'
)
它读取到第一个换行符(不包括它)或字符串的结尾,以先到者为准,并去除任何前导和尾随空格以及\t
字符的混合。如果要保留多行(以及带前导和尾随的换行符),请使用read-r-d''var#修剪指定参数两端的空白
修剪(){
读取-rd'$1要从左到第一个单词删除空格和制表符,请输入:
echo“这是一个测试”| sed“s/^[\t]*/”
我只想使用sed:
function trim
{
echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}
a)单行字符串的用法示例
string=' wordA wordB wordC wordD '
trimmed=$( trim "$string" )
echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"
string=' wordA
>wordB<
wordC '
trimmed=$( trim "$string" )
echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"
输出:
'one leading', 'one trailing', 'one leading and one trailing'
'two leading', 'two trailing', 'two leading and two trailing'
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
wordA wordB wordC
wordAA
>four spaces before<
>one space before<
>here is
something<
test
b)多行字符串的用法示例
string=' wordA wordB wordC wordD '
trimmed=$( trim "$string" )
echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"
string=' wordA
>wordB<
wordC '
trimmed=$( trim "$string" )
echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"
例如:
echo " wordA wordB wordC " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
输出:
'one leading', 'one trailing', 'one leading and one trailing'
'two leading', 'two trailing', 'two leading and two trailing'
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
wordA wordB wordC
wordAA
>four spaces before<
>one space before<
>here is
something<
test
在多行字符串上使用上述命令同样有效,但请注意,正如GuruM在评论中注意到的那样,它也会剪切任何尾随/前导的内部多行空格
string=' wordAA
>four spaces before<
>one space before< '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
一个简单的答案是:
echo " lol " | xargs
这是一个命令/程序,没有参数,返回修剪过的字符串,就这么简单
注意:这不会删除所有内部空格,因此“foo bar”
保持不变;它不会变成“foobar”
。但是,多个空格将压缩为单个空格,因此“foo bar”
将变成“foo bar”
。此外,它不会删除行尾字符。您只需使用echo
:
foo=" qsdqsd qsdqs q qs "
# Not trimmed
echo \'$foo\'
# Trim
foo=`echo $foo`
# Trimmed
echo \'$foo\'
这将删除字符串中的所有空白
VAR2="${VAR2//[[:space:]]/}"
/
替换字符串中第一次出现的空格和所有出现的空格。也就是说,所有空格都被–nothing替换。这是我见过的最简单的方法。它只使用B