文字列に改行文字があると断言し、もしあれば、それを削除する方法


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

これが原因であるかどうかを確認し、原因newlineである場合は削除するにはどうすればよいですか?


1
Bashではprintf '%q\n' "$string"、任意の文字列のエスケープバージョンを取得できます。例:printf '%q\n' 'foo\n'-> foo\\n; printf '%q\n' $'foo\n'->$'foo\n'
l0b0

1
変数の展開を引用しているわけではありません。末尾に空白がある場合は、で表示されませんecho $fooecho "$foo"代わりにしてください。
Peter Cordes、2015

回答:


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)をテストしてそれらを削除することにより、テストと修正を1つのステップで組み合わせることができます。

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

修正は使用していますシェルパラメータ展開を。:上記使用される特定のフォームはあなたのproovidedパターンに基づいて、部分文字列の交換のためである${parameter/pattern/string}-この置き換えのみ最初に見つかったの< パターン文字列の引数*という名前の変数にします。交換するには、すべてのパターンを、あなただけの最初に変更する必要がある/のを//


最後のコードについて説明していただけますか?fix="....ライン?
farid99

@ farid99:答えに追加説明、注意をfixすることができvar、それ自体-または-であるとして、多くの場合、あなただけの(おそらく)変更された値を再割り当てすることなく、パラメータ展開を使用することができます。..
Peter.O

5

あなたはbashの\rよう$'\r'に表すことができます:

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

または最後\rを切りmyvarます:

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

3

不思議なことに、多くのシェルでgetoptsは、このような仕事に非常に有望です。これは最初は直感に反するように思えるかもしれませんが、getopts'主な機能は、連結された一連の同じように、指定された1文字のコマンドラインオプションを認識して解釈できるようにすることです。もっと感覚。

実例として、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このようにして、このような場合に分解を一種のシェル自動操縦装置として処理できるようにすると便利な場合があります。その場合は、不要なバイトをw / 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や他のシェル言語は便利ですが、Perlのような真のスクリプト言語を使用した方がよい場合もあります。Perlは、sedやawkなどの他の言語を呼び出すシェルスクリプトやUNIXコマンドを非常に簡単に置き換えることができます。FORTRANコードを呼び出す前に、sed、awk、およびさまざまなUNIXコマンドを呼び出すC-Shellスクリプトを書くときに、20年以上前にこれを学びました。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";
  }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.