string 如何从 Bash 变量中修剪空格?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/369758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:20:57  来源:igfitidea点击:

How to trim whitespace from a Bash variable?

stringbashvariablestrim

提问by too much php

I have a shell script with this code:

我有一个带有此代码的shell脚本:

var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

But the conditional code always executes, because hg stalways prints at least one newline character.

但是条件代码总是会执行,因为hg st总是至少打印一个换行符。

  • Is there a simple way to strip whitespace from $var(like trim()in PHP)?
  • 有没有一种简单的方法来去除空格$var(比如trim()PHP 中)?

or

或者

  • Is there a standard way of dealing with this issue?
  • 有没有标准的方法来处理这个问题?

I could use sedor AWK, but I'd like to think there is a more elegant solution to this problem.

我可以使用sedAWK,但我想有一个更优雅的解决方案来解决这个问题。

回答by MattyV

Let's define a variable containing leading, trailing, and intermediate whitespace:

让我们定义一个包含前导、尾随和中间空格的变量:

FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16


How to remove all whitespace (denoted by [:space:]in tr):

如何删除所有空格(用[:space:]in表示tr):

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


How to remove leading whitespace only:

如何仅删除前导空格:

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


How to remove trailing whitespace only:

如何仅删除尾随空格:

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


How to remove both leading and trailing spaces--chain the seds:

如何删除前导和尾随空格 - 链接seds:

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

Alternatively, if your bash supports it, you can replace echo -e "${FOO}" | sed ...with sed ... <<<${FOO}, like so (for trailing whitespace):

或者,如果您的 bash 支持它,您可以替换echo -e "${FOO}" | sed ...sed ... <<<${FOO},像这样(用于尾随空格):

FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"

回答by makevoid

A simple answer is:

一个简单的答案是:

echo "   lol  " | xargs

Xargswill do the trimming for you. It's one command/program, no parameters, returns the trimmed string, easy as that!

Xargs将为您进行修剪。这是一个命令/程序,没有参数,返回修剪后的字符串,就这么简单!

Note: this doesn't remove all internal spaces so "foo bar"stays the same; it does NOT become "foobar". However, multiple spaces will be condensed to single spaces, so "foo bar"will become "foo bar". In addition it doesn't remove end of lines characters.

注意:这不会删除所有内部空间,因此"foo bar"保持不变;它不会变成"foobar". 但是,多个空格会被压缩为单个空格,因此"foo bar"会变成"foo bar". 此外,它不会删除行尾字符。

回答by bashfu

There is a solution which only uses Bash built-ins called wildcards:

有一个只使用 Bash 内置插件的解决方案,称为通配符

var="    abc    "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"   
printf '%s' "===$var==="

Here's the same wrapped in a function:

这是封装在函数中的相同内容:

trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"   
    printf '%s' "$var"
}

You pass the string to be trimmed in quoted form. e.g.:

您以引号形式传递要修剪的字符串。例如:

trim "   abc   "

A nice thing about this solution is that it will work with any POSIX-compliant shell.

这个解决方案的一个好处是它可以与任何符合 POSIX 的 shell 一起工作。

Reference

参考

回答by bashfu

Bash has a feature called parameter expansion, which, among other things, allows string replacement based on so-called patterns(patterns resemble regular expressions, but there are fundamental differences and limitations). [flussence's original line: Bash has regular expressions, but they're well-hidden:]

Bash 有一个称为参数扩展的特性,除其他外,它允许基于所谓的模式(模式类似于正则表达式,但存在根本差异和限制)的字符串替换。[flussence 的原话:Bash 有正则表达式,但它们隐藏得很好:]

The following demonstrates how to remove allwhite space (even from the interior) from a variable value.

下面演示了如何从变量值中删除所有空白(甚至从内部)。

$ 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

回答by rkachach

In order to remove all the spaces from the beginning and the end of a string (including end of line characters):

为了删除字符串开头和结尾的所有空格(包括行尾字符):

echo $variable | xargs echo -n

This will remove duplicate spaces also:

这也将删除重复的空格:

echo "  this string has a lot       of spaces " | xargs echo -n

Produces: 'this string has a lot of spaces'

产生:'这个字符串有很多空格'

回答by Brian Cain

Strip one leading and one trailing space

去掉一个前导和一个尾随空格

trim()
{
    local trimmed=""

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

For example:

例如:

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

Output:

输出:

'one leading', 'one trailing', 'one leading and one trailing'

Strip allleading and trailing spaces

去除所有前导和尾随空格

trim()
{
    local trimmed=""

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

For example:

例如:

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

Output:

输出:

'two leading', 'two trailing', 'two leading and two trailing'

回答by GuruM

From Bash Guide section on globbing

来自 Bash 指南关于globbing 的部分

To use an extglob in a parameter expansion

在参数扩展中使用 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  

Here's the same functionality wrapped in a function (NOTE: Need to quote input string passed to function):

这是封装在函数中的相同功能(注意:需要引用传递给函数的输入字符串):

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=
    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.
}

Usage:

用法:

string="   abc def ghi  ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");  
echo "$trimmed";


If we alter the function to execute in a subshell, we don't have to worry about examining the current shell option for extglob, we can just set it without affecting the current shell. This simplifies the function tremendously. I also update the positional parameters "in place" so I don't even need a local variable

如果我们将函数更改为在子 shell 中执行,我们不必担心检查 extglob 的当前 shell 选项,我们可以设置它而不影响当前 shell。这极大地简化了功能。我还“就地”更新了位置参数,所以我什至不需要局部变量

trim() {
    shopt -s extglob
    set -- "${1##+([[:space:]])}"
    printf "%s" "${1%%+([[:space:]])}" 
}

so:

所以:

$ s=$'\t\n \r\tfoo  '
$ shopt -u extglob
$ shopt extglob
extglob         off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo  '<
>foo<
$ shopt extglob
extglob         off

回答by VAmp

You can trim simply with echo:

你可以简单地修剪echo

foo=" qsdqsd qsdqs q qs   "

# Not trimmed
echo \'$foo\'

# Trim
foo=`echo $foo`

# Trimmed
echo \'$foo\'

回答by Paul Tomblin

I've always done it with sed

我一直都是用 sed 做的

  var=`hg st -R "$path" | sed -e 's/  *$//'`

If there is a more elegant solution, I hope somebody posts it.

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

回答by Adam Rosenfield

You can delete newlines with tr:

您可以使用以下命令删除换行符tr

var=`hg st -R "$path" | tr -d '\n'`
if [ -n $var ]; then
    echo $var
done