Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.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
String 如何修剪Bash变量中的空白?_String_Bash_Variables_Trim - Fatal编程技术网

String 如何修剪Bash变量中的空白?

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/ *$//

我有一个包含以下代码的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/  *$//'`

如果有一个更优雅的解决方案,我希望有人发布。

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