如何断言字符串具有换行符,如果有,请将其删除


9

我有一个字符串,这是我无法控制的某些操作的结果。当我使用打印此变量时echo,我得到:

echo $myvar
hello

但是,当我这样做

if [ $myvar = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

我总是得到他们不平等。我怀疑这是因为newline角色。

该字符串的行为也很奇怪。当我做:

newVAR="this is my var twice: "$myvar$myvar
echo $newVAR

我得到:

hellois my var twice: hello

如何检查这是否实际上是由于a引起的newline,如果是,将其删除?


1
在Bash中,您可以printf '%q\n' "$string"获取任何字符串的转义版本。例如:printf '%q\n' 'foo\n'-> foo\\n; printf '%q\n' $'foo\n'->$'foo\n'
l0b0

1
您没有引用任何变量的扩展。如果他们确实有任何尾随空格,则不会显示echo $foo。做吧echo "$foo"
彼得·科德斯

Answers:


9

问题是您有一个嵌入式的回车符(CR,\r)。这将导致终端文本插入点退回到其正在打印的行的开头。这就是为什么您在$newVAR示例中的行首看到“ hello”的原因- sed -n l显示可读的不可打印字符视图(和行尾)。

var=ab$'\r'c ; echo "$var";  printf %s "$var" | sed -n l
# output:
cb
ab\rc$

您可以通过简单的bash条件检查来测试它:

[[ $var == *$'\r'* ]] && echo yes || echo no
# output:
yes

您可以通过测试\r(s)并通过以下方法将其删除来一步一步地将测试和修复结合起来:

fix="${var//$'\r'/}"; echo "$var"; echo "$fix"
# output:
cb
abc

修复程序使用Shell参数扩展。上面所用的特定形式是用于替换基于你proovided图案子:${parameter/pattern/string}< -这仅替换第一个找到的图案在名为*参数变量。要替换所有模式,只需将第一个更改///


您能解释一下最后的代码吗?该fix="....行?
farid99

@ farid99:添加到答案的解释,说明fix可能是var本身-或者经常可以只使用参数扩展原样而不需要重新分配(可能)修正值..
Peter.O

5

你可以表示\r$'\r'在bash:

if [ "$myvar" = "hello"$'\r' ]; then
    echo they are equal
else
    echo they are not equal
fi

剁最后\rmyvar

if [ "${myvar%$'\r'*}" = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

3

奇怪的是,在很多情况下getopts,这样的工作很可能是候选人。乍一看,这似乎是违反直觉的,但是,如果您认为getopts“主要功能是识别并提供解释以供在一系列串联的指定单字符命令行选项中找到,则它可能会产生一些作用。更有意义。

为了演示,从bash外壳:

x=$(printf '\n\r%010s\t' hello)
OPTIND=1
while  getopts : na "-$x"
do     printf %q\\n "$OPTARG"
done

$'\n'
$'\r'
\
\
\
\
\
h
e
l
l
o
$'\t'

这样,在这种情况下,有时可以方便地getopts将拆卸作为一种外壳自动驾驶仪进行处理。这样做时,您可以筛选出不需要的字节(带a)case或进行[测试,]并从字节1开始备份字符串:

OPTIND=1 y=$(printf \\n\\r) z=
while  getopts : na "-$x"
do     case $OPTARG in ([!$y])
            z=$z$OPTARG
       esac
done
printf %q\\n "$z"

$'     hello\t'

考虑到这个简单的示例案例-并提供了一个支持参数扩展的外壳程序,该扩展可能会在这里为您提供更好的服务。但是getopts,如果您不知道它在这方面的功能,我想也值得一提。当然,当我了解它时,无论如何,我发现了许多有用的应用程序。


0

虽然Bash和其他Shell语言很方便,但有时最好使用真正的脚本语言-如Perl。Perl可以很容易地替换调用sed和awk等其他语言的shell脚本以及UNIX命令。20年前,我在编写C-Shell脚本(在调用FORTRAN代码之前,依次称为sed,awk和各种UNIX命令)时学到了这一点。在Perl中,我会这样做:

chomp($myvar);   # removes the newline char

if("$myvar" eq "hello")   # string comparison
  {
  print "they are equal\n";
  }
else
  {
  print "they are not equal\n";
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.