提问人: 提问时间:12/16/2008 最后编辑:4 revs, 3 users 79%too much php 更新时间:6/30/2023 访问量:1914009
如何从 Bash 变量中修剪空格?
How to trim whitespace from a Bash variable?
问:
我有一个带有此代码的 shell 脚本:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
但是条件代码始终执行,因为始终打印至少一个换行符。hg st
- 有没有一种简单的方法可以去除空格(如在PHP中)?
$var
trim()
或
- 有没有处理这个问题的标准方法?
答:
我一直用 sed 来做
var=`hg st -R "$path" | sed -e 's/ *$//'`
如果有更优雅的解决方案,我希望有人发布它。
评论
sed
sed -e 's/\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
评论
${var/ /}
删除第一个空格字符。 删除所有空格字符。仅使用此构造无法仅修剪前导和尾随空格。${var// /}
=~
extglob
^
$
man bash
man 7 regex
您可以使用以下命令删除换行符:tr
var=`hg st -R "$path" | tr -d '\n'`
if [ -n $var ]; then
echo $var
done
评论
var=`hg...`
我见过脚本只是使用变量赋值来完成这项工作:
$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar
空格会自动合并和修剪。必须注意外壳元字符(潜在的注入风险)。
我还建议始终在 shell 条件中用双引号引用变量替换:
if [ -n "$var" ]; then
因为变量中的 -o 或其他内容可能会修改您的测试参数。
评论
$xyz
echo
xyz=$(echo -n $xyz)
xyz
去除一个前导空格和一个尾随空格
trim()
{
local trimmed="$1"
# Strip leading space.
trimmed="${trimmed## }"
# Strip trailing space.
trimmed="${trimmed%% }"
echo "$trimmed"
}
例如:
test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"
输出:
'one leading', 'one trailing', 'one leading and one trailing'
去除所有前导和尾随空格
trim()
{
local trimmed="$1"
# Strip leading spaces.
while [[ $trimmed == ' '* ]]; do
trimmed="${trimmed## }"
done
# Strip trailing spaces.
while [[ $trimmed == *' ' ]]; do
trimmed="${trimmed%% }"
done
echo "$trimmed"
}
例如:
test4="$(trim " two leading")"
test5="$(trim "two trailing ")"
test6="$(trim " two leading and two trailing ")"
echo "'$test4', '$test5', '$test6'"
输出:
'two leading', 'two trailing', 'two leading and two trailing'
评论
'hello world ', 'foo bar', 'both sides '
``
$()
使用 AWK:
echo $var | awk '{gsub(/^ +| +$/,"")}1'
评论
$stripped_version=
您可以使用老式.例如,这将返回 git 存储库中已修改文件的数量,其中有空格被剥离。tr
MYVAR=`git ls-files -m|wc -l|tr -d ' '`
评论
启用 Bash 的扩展模式匹配功能 () 后,您可以使用以下命令:shopt -s extglob
{trimmed##*( )}
以删除任意数量的前导空格。
评论
/bin/sh -o posix
trimmed
将空格删除为一个空格:
(text) | fmt -su
让我们定义一个包含前导、尾随和中间空格的变量:
FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16
如何删除所有空格(用 表示):[:space:]
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
如何仅删除前导空格:
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
如何删除前导空格和尾随空格 - 链接 s:sed
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 支持它,你可以用 替换 ,如下所示(对于尾随空格):echo -e "${FOO}" | sed ...
sed ... <<<${FOO}
FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"
评论
tr
sed
[[:space:]]
sed
trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"
~/.profile
echo $SOMEVAR | trim
cat somefile | trim
echo -e "${FOO}" | wc -m
echo -ne "${FOO}" | wc -m
sed
sed
[[:space:]]
tr -d "[:space:]"
tr -d " "
使用 Bash 内置(称为通配符)的解决方案:
var=" abc "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "===$var==="
下面是包装在函数中的相同内容:
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "$var"
}
你以引号的形式传递要修剪的字符串,例如:
trim " abc "
此解决方案适用于符合 POSIX 的 shell。
参考
评论
s=" 1 2 3 "; echo \""${s%1 2 3 }"\"
" "
1 2 3
[![:space:]]*
%%
%
" "
/bin/sh
/usr/xpg4/bin/sh
${var%%[![:space:]]*}
var
${var#..
awk
sed
tr
xargs
赋值忽略前导和尾随空格,因此可用于修剪:
$ var=`echo ' hello'`; echo $var
hello
评论
echo "$var"
var=$(echo $var)
这将修剪前端和末端的多个空间
whatever=${whatever%% *}
whatever=${whatever#* }
评论
##
#
*
*
*
" foo "
"foo"
" hello world "
t=" "" a "" "; echo "=${t#* }="
输出前导多个空格不会被剥离。 输出尾随空格使用字符串内容进行剥离。(由于 SE 而重复引用。= a =
t=" "" a "" "; echo "=${t%% *}="
==
我创建了以下函数。我不确定 printf 的可移植性如何,但这个解决方案的美妙之处在于您可以通过添加更多字符代码来准确指定什么是“空白”。
iswhitespace()
{
n=`printf "%d\n" "'$1'"`
if (( $n != "13" )) && (( $n != "10" )) && (( $n != "32" )) && (( $n != "92" )) && (( $n != "110" )) && (( $n != "114" )); then
return 0
fi
return 1
}
trim()
{
i=0
str="$1"
while (( i < ${#1} ))
do
char=${1:$i:1}
iswhitespace "$char"
if [ "$?" -eq "0" ]; then
str="${str:$i}"
i=${#1}
fi
(( i += 1 ))
done
i=${#str}
while (( i > "0" ))
do
(( i -= 1 ))
char=${str:$i:1}
iswhitespace "$char"
if [ "$?" -eq "0" ]; then
(( i += 1 ))
str="${str:0:$i}"
i=0
fi
done
echo "$str"
}
#Call it like so
mystring=`trim "$mystring"`
当变量设置为其他内容时,我需要从脚本中修剪空格。依靠Perl做到了: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() { local IFS=$' \t\n'; echo $1; }
The default value of IFS is space, tab, newline. (A three-character string.)
这是一个 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'
评论
*
local IFS=$' \t\n'
\t
\n
if
if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]
if
[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
摘自《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
下面是封装在函数中的相同功能(注意:需要引用传递给函数的输入字符串):
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.
}
用法:
string=" abc def ghi ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");
echo "$trimmed";
如果我们更改函数以在子 shell 中执行,我们不必担心检查 extglob 的当前 shell 选项,我们可以在不影响当前 shell 的情况下设置它。这极大地简化了功能。我还“就地”更新了位置参数,因此我甚至不需要局部变量
trim() {
shopt -s extglob
set -- "${1##+([[:space:]])}"
printf "%s" "${1%%+([[:space:]])}"
}
所以:
$ 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
评论
extglob
shopt -p
local restore="$(shopt -p extglob)" ; shopt -s extglob
eval "$restore"
[[:space:]]
${var##+( )}
${var%%+( )}
另一个带有单元测试的解决方案,它从 stdin 修剪,并与任何输入分隔符(偶数)一起使用:$IFS
$'\0'
ltrim()
{
# Left-trim $IFS from stdin as a single line
# $1: Line separator (default NUL)
local trimmed
while IFS= read -r -d "${1-}" -u 9
do
if [ -n "${trimmed+defined}" ]
then
printf %s "$REPLY"
else
printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
fi
printf "${1-\x00}"
trimmed=true
done 9<&0
if [[ $REPLY ]]
then
# No delimiter at last line
if [ -n "${trimmed+defined}" ]
then
printf %s "$REPLY"
else
printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
fi
fi
}
rtrim()
{
# Right-trim $IFS from stdin as a single line
# $1: Line separator (default NUL)
local previous last
while IFS= read -r -d "${1-}" -u 9
do
if [ -n "${previous+defined}" ]
then
printf %s "$previous"
printf "${1-\x00}"
fi
previous="$REPLY"
done 9<&0
if [[ $REPLY ]]
then
# No delimiter at last line
last="$REPLY"
printf %s "$previous"
if [ -n "${previous+defined}" ]
then
printf "${1-\x00}"
fi
else
last="$previous"
fi
right_whitespace="${last##*[!$IFS]}"
printf %s "${last%$right_whitespace}"
}
trim()
{
# Trim $IFS from individual lines
# $1: Line separator (default NUL)
ltrim ${1+"$@"} | rtrim ${1+"$@"}
}
这不存在不需要的通配的问题,此外,内部空白是未修改的(假设设置为默认值,即 )。$IFS
' \t\n'
它读取到第一个换行符(不包括它)或字符串的末尾,以先到者为准,并去除任何前导和尾随空格和字符的混合。如果要保留多行(并去除前导和尾随换行符),请改用;但是请注意,如果您的输入恰好包含 ,它将在之前被截断。(其他形式的空格(即 、 和 )不会被剥离,即使将它们添加到$IFS中也是如此。\t
read -r -d '' var << eof
\neof
\r
\f
\v
read -r var << eof
$var
eof
#!/bin/bash
function trim
{
typeset trimVar
eval trimVar="\${$1}"
read trimVar << EOTtrim
$trimVar
EOTtrim
eval $1=\$trimVar
}
# Note that the parameter to the function is the NAME of the variable to trim,
# not the variable contents. However, the contents are trimmed.
# Example of use:
while read aLine
do
trim aline
echo "[${aline}]"
done < info.txt
# File info.txt contents:
# ------------------------------
# ok hello there $
# another line here $
#and yet another $
# only at the front$
#$
# Output:
#[ok hello there]
#[another line here]
#[and yet another]
#[only at the front]
#[]
# Trim whitespace from both ends of specified parameter
trim () {
read -rd '' $1 <<<"${!1}"
}
# Unit test for trim()
test_trim () {
local foo="$1"
trim foo
test "$foo" = "$2"
}
test_trim hey hey &&
test_trim ' hey' hey &&
test_trim 'ho ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim ' hey ho ' 'hey ho' &&
test_trim $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' &&
test_trim $'\n' '' &&
test_trim '\n' '\n' &&
echo passed
评论
read -rd '' str < <(echo "$str")
trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
read -rd '' str <<<"$str"
我发现我需要从混乱的输出中添加一些代码来清理它:sdiff
sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt
sed -n 1'p' c12diff.txt | sed 's/ *$//g' | tr -d '\n' | tr -d '\t'
这将删除尾随空格和其他不可见字符。
使用这个简单的 Bash 参数扩展:
$ x=" a z e r ty "
$ echo "START[${x// /}]END"
START[azerty]END
评论
trim() 删除空格(和制表符,不可打印的字符;为了简单起见,我只考虑空格)。我的解决方案版本:
var="$(hg st -R "$path")" # I often like to enclose shell output in double quotes
var="$(echo "${var}" | sed "s/\(^ *\| *\$\)//g")" # This is my suggestion
if [ -n "$var" ]; then
echo "[${var}]"
fi
“sed”命令仅修剪前导和尾随空格,但它也可以通过管道传递到第一个命令,从而产生:
var="$(hg st -R "$path" | sed "s/\(^ *\| *\$\)//g")"
if [ -n "$var" ]; then
echo "[${var}]"
fi
要删除从左到第一个单词的空格和制表符,请输入:
echo " This is a test" | sed "s/^[ \t]*//"
cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html
我会简单地使用 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|"
输出:
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
b) 多行字符串的使用示例
string=' wordA
>wordB<
wordC '
trimmed=$( trim "$string" )
echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"
输出:
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
c) 最后说明:如果您不喜欢使用函数,对于单行字符串,您可以简单地使用“更容易记住”的命令,例如:
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
例:
echo " wordA wordB wordC " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
输出:
wordA wordB wordC
在多行字符串上使用上述内容也可以,但请注意,正如 GuruM 在评论中指出的那样,它也会削减任何尾随/前导内部多个空格
string=' wordAA
>four spaces before<
>one space before< '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
输出:
wordAA
>four spaces before<
>one space before<
因此,如果您介意保留这些空格,请使用我答案开头的功能!
d) 对函数修剪中使用的多行字符串的 sed 语法“查找和替换”的解释:
sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
# Copy from the hold to the pattern buffer
g
# Do the search and replace
s/^[ \t]*//g
s/[ \t]*$//g
# print
p
}'
评论
一个简单的答案是:
echo " lol " | xargs
Xargs 将为您进行修剪。它是一个命令/程序,没有参数,返回修剪后的字符串,就这么简单!
注意:这不会删除所有内部空格,因此保持不变;它不会成为.但是,多个空间将压缩为单个空间,因此将成为 .此外,它不会删除行尾字符。"foo bar"
"foobar"
"foo bar"
"foo bar"
评论
xargs echo
sed 's/ *$//'
xargs
echo -n "hey thiss " | xargs | hexdump
0a73
a
sed
echo -n "hey thiss " | sed 's/ *$//' | hexdump
0073
a<space><space>b
a<space>b
a"b"c'd'e
abcde
a"b
虽然它不是严格意义上的 Bash,但它会做你想做的事,甚至更多:
php -r '$x = trim(" hi there "); echo $x;'
如果您也想将其设为小写,请执行以下操作:
php -r '$x = trim(" Hi There "); $x = strtolower($x) ; echo $x;'
var=" a b "
echo "$(set -f; echo $var)"
>a b
您可以简单地修剪:echo
foo=" qsdqsd qsdqs q qs "
# Not trimmed
echo \'$foo\'
# Trim
foo=`echo $foo`
# Trimmed
echo \'$foo\'
评论
foo
foo=" I * have a wild card"
#Execute this script with the string argument passed in double quotes !!
#var2 gives the string without spaces.
#$1 is the string passed in double quotes
#!/bin/bash
var2=`echo $1 | sed 's/ \+//g'`
echo $var2
var=' a b c '
trimmed=$(echo $var)
评论
echo $(echo "1 2 3")
这将从你的字符串中删除所有的空格,
VAR2="${VAR2//[[:space:]]/}"
/
替换字符串中第一次出现的空格和所有出现的空格。即所有空格都被 – 什么都没有替换//
用:
var=`expr "$var" : "^\ *\(.*[^ ]\)\ *$"`
我相信,它消除了前导和尾随空格,是最基本的解决方案。不是 Bash 内置的,但“expr”是 coreutils 的一部分,因此至少不需要像 sed 或 AWK 这样的独立实用程序。
这是我见过的最简单的方法。它只使用 Bash,只有几行,正则表达式很简单,并且匹配所有形式的空格:
if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then
test=${BASH_REMATCH[1]}
fi
下面是一个用于测试它的示例脚本:
test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t \n ")
echo "Let's see if this works:"
echo
echo "----------"
echo -e "Testing:${test} :Tested" # Ugh!
echo "----------"
echo
echo "Ugh! Let's fix that..."
if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then
test=${BASH_REMATCH[1]}
fi
echo
echo "----------"
echo -e "Testing:${test}:Tested" # "Testing:Spaces and tabs and newlines be gone!"
echo "----------"
echo
echo "Ah, much better."
评论
^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
Python有一个与PHP相同的函数,因此我们可以做一些内联Python来为此制作一个易于理解的实用程序:strip()
trim()
alias trim='python -c "import sys; sys.stdout.write(sys.stdin.read().strip())"'
这将修剪前导和尾随空格(包括换行符)。
$ x=`echo -e "\n\t \n" | trim`
$ if [ -z "$x" ]; then echo hi; fi
hi
评论
如果您已启用,那么下面是一个简洁的解决方案。shopt -s extglob
这对我有用:
text=" trim my edges "
trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back
echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed
#Result
<trim my edges>
为了获得相同的结果,将其放在更少的行上:
text=" trim my edges "
trimmed=${${text##+( )}%%+( )}
评论
${var##Pattern}
##
%%
+( )
#!/bin/sh
用:
trim() {
local orig="$1"
local trmd=""
while true;
do
trmd="${orig#[[:space:]]}"
trmd="${trmd%[[:space:]]}"
test "$trmd" = "$orig" && break
orig="$trmd"
done
printf -- '%s\n' "$trmd"
}
- 它适用于各种空格,包括换行符、
- 它不需要修改 shopt。
- 它保留内部空格,包括换行符。
单元测试(用于人工审核):
#!/bin/bash
. trim.sh
enum() {
echo " a b c"
echo "a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a b c "
echo " a N b c "
echo "N a N b c "
echo " Na b c "
echo " a b c N "
echo " a b c N"
}
xcheck() {
local testln result
while IFS='' read testln;
do
testln=$(tr N '\n' <<<"$testln")
echo ": ~~~~~~~~~~~~~~~~~~~~~~~~~ :" >&2
result="$(trim "$testln")"
echo "testln='$testln'" >&2
echo "result='$result'" >&2
done
}
enum | xcheck
答案有很多,但我仍然相信我刚刚写的剧本值得一提,因为:
- 它在 shells bash/dash/busybox shell 中成功测试
- 它非常小
- 它不依赖于外部命令,也不需要分叉(->快速和低资源使用率)
- 它按预期工作:
- 它从开头和结尾剥离所有空格和制表符,但不会更多
- 重要提示:它不会从字符串中间删除任何内容(许多其他答案会删除),甚至换行符也会保留
- 特殊:使用一个空格连接多个参数。如果您只想修剪和输出第一个参数,请改用
"$*"
"$1"
- 如果在匹配文件名模式等方面没有任何问题
脚本:
trim() {
local s2 s="$*"
until s2="${s#[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
until s2="${s%[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
echo "$s"
}
用法:
mystring=" here is
something "
mystring=$(trim "$mystring")
echo ">$mystring<"
输出:
>here is
something<
评论
[\ \t]
[[:space:]]
为了删除字符串开头和结尾的所有空格(包括行尾字符):
echo $variable | xargs echo -n
这也将删除重复的空格:
echo " this string has a lot of spaces " | xargs echo -n
Produces: 'this string has a lot of spaces'
评论
echo -n
echo " my string " | xargs
# Strip leading and trailing white space (new line inclusive).
trim(){
[[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
printf "%s" "$BASH_REMATCH"
}
或
# Strip leading white space (new line inclusive).
ltrim(){
[[ "$1" =~ [^[:space:]].* ]]
printf "%s" "$BASH_REMATCH"
}
# Strip trailing white space (new line inclusive).
rtrim(){
[[ "$1" =~ .*[^[:space:]] ]]
printf "%s" "$BASH_REMATCH"
}
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "$(rtrim "$(ltrim "$1")")"
}
或
# Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a')
trim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
printf "%s" "${BASH_REMATCH[1]}"
}
或
# Strip leading specified characters. ex: str=$(ltrim "$str" $'\n a')
ltrim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]]
printf "%s" "${BASH_REMATCH[1]}"
}
# Strip trailing specified characters. ex: str=$(rtrim "$str" $'\n a')
rtrim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
printf "%s" "${BASH_REMATCH[1]}"
}
# Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a')
trim(){
printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")"
}
或
建立在 moskit 的 expr soulution 之上......
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`"
}
或
# Strip leading white space (new line inclusive).
ltrim(){
printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`"
}
# Strip trailing white space (new line inclusive).
rtrim(){
printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`"
}
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "$(rtrim "$(ltrim "$1")")"
}
我必须测试命令的结果(数字),但结果的变量似乎包含空格和一些不可打印的字符。因此,即使在“修剪”之后,比较也是错误的。 我通过从变量中提取数值部分来解决它:
numerical_var=$(echo ${var_with_result_from_command} | grep -o "[0-9]*")
这就是我所做的,并且做得完美而简单:
the_string=" test"
the_string=`echo $the_string`
echo "$the_string"
输出:
test
评论
数组赋值在内部字段分隔符(默认为空格/制表符/换行符)上扩展其参数拆分。
words=($var)
var="${words[@]}"
“trim”函数删除所有水平空格:
ltrim () {
if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/^\h+//g'
return $?
}
rtrim () {
if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/\h+$//g'
return $?
}
trim () {
ltrim "$@" | rtrim
return $?
}
在 BASH 中有几个不同的选项:
line=${line##+([[:space:]])} # strip leading whitespace; no quote expansion!
line=${line%%+([[:space:]])} # strip trailing whitespace; no quote expansion!
line=${line//[[:space:]]/} # strip all whitespace
line=${line//[[:space:]]/} # strip all whitespace
line=${line//[[:blank:]]/} # strip all blank space
前两个需要先验设置/启用:extglob
shopt -s extglob # bash only
注意:引号内的变量扩展会破坏前两个示例!
此处详细介绍了 POSIX 括号表达式的模式匹配行为。如果您使用的是更现代/更可破解的 shell,例如 Fish,则有用于字符串修剪的内置函数。
最简单和最便宜的方法是利用回声忽略空间。所以,只需使用
dest=$(echo $source)
例如:
> VAR=" Hello World "
> echo "x${VAR}x"
x Hello World x
> TRIMD=$(echo $VAR)
> echo "x${TRIMD}x"
xHello Worldx
请注意,这也会将多个空格折叠为一个空格。
评论
read
已经修剪了空格,所以在 bash 中你可以这样做:
$ read foo <<< " foo bar two spaces follow "
$ echo ".$foo."
.foo bar two spaces follow.
POSIX兼容版本稍长一些
$ read foo << END
foo bar two spaces follow
END
$ echo ".$foo."
.foo bar two spaces follow.
对于我所知道的单行用例,最简单的方法:
echo " ABC " | sed -e 's# \+\(.\+\) \+#\1#'
工作原理:
-e
启用高级正则表达式- 我使用,因为我不喜欢“凌乱的库”模式,比如
#
sed
/\////\/\\\/\/
sed
希望大多数正则表达式控件字符转义,因此所有\
- 否则,它只是 ,即开头的空格、第 1 组和结尾的空格。
^ +(.+) +$
- 所有这些都被替换为“第一组”。
因此,成为 . ABC
ABC
在具有 的最新系统上应支持此功能。sed
对于选项卡,这将是
echo " ABC " | sed -e 's#[\t ]\+\(.\+\)[\t ]\+#\1#'
对于多行内容,这已经需要字符类,如其他答案中所述,并且可能并非所有实现都支持。[:space:]
sed
参考:Sed 手册
评论
-e
不启用高级正则表达式。你的意思是(你不需要任何那些反斜杠)?-E
创建一个数组而不是变量,这将修剪所有空格、制表符和换行符:
arr=( $(hg st -R "$path") )
if [[ -n "${arr[@]}" ]]; then
printf -- '%s\n' "${arr[@]}"
fi
var = ' a b '
# remove all white spaces
new=$(echo $var | tr -d ' ')
# remove leading and trailing whitespaces
new=$(echo $var)
ab
a b
评论
一个简单的答案是:
sed 's/^\s*\|\s*$//g'
举个例子:
$ before=$( echo -e " \t a b \t ")
$ echo "(${before})"
( a b )
$ after=$( echo "${before}" | sed 's/^\s*\|\s*$//g' )
$ echo "(${after})"
(a b)
上一个:如何检查变量是否存在?
下一个:从键/值对文件设置环境变量
评论
$ var=$(echo)
$ [ -n $var ]; echo $? #undesired test return
0
$ [[ -n $var ]]; echo $?
1
echo " This is a string of char " | xargs
echo " This i's a string of char " | xargs -0
test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi
test=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi
echo $A | sed -r 's/( )+//g'
;