
readvar.shというスクリプトがあります。
#! /bin/bash
a="$1"
echo "$a"
パラメータを取得したいです。文字通りユーザーが入力すると、
たとえば、ユーザーが次を実行する場合:./readvar.sh \\
\\
パラメータの周囲に引用符なしで出力する必要があります。
それは可能ですか?
答え1
一般的に言えば、これはできません。
runの場合、./readvar.sh \\
コマンドが書かれたシェルはコマンドラインを解析し、スペースを単語区切り文字として認識し、バックスラッシュを次の文字(別のバックスラッシュ)を引用することを認識します。その後、./readvar.sh
2つの単語で終わり、\
プログラムを起動して./readvar.sh
その2つの単語をプロセスを開始するパラメータのリストに入れます。 (コマンド名はargv[0]
Cプログラムに出てくるパラメータ#0です。)
./readvar.sh '\'
ユーザーがPerlプログラムなどを使用してスクリプトを入力または起動すると、同様のbs='\'; ./readvar "$var"
結果が得られます。system("./readvar.sh", "\\");
スクリプトには通常、何が起こっているのかを知る方法はありません。
あなたができることは、シェル入力に適した形式ですべての引数を印刷することです。たとえば、Bashでは次のように使用します。
if [ "$#" -ne 0 ]; then
printf "%q " "$@"
fi
echo
出力はBashで動作しますが、$'\n'
改行などの形式で引用符を使用するため、標準シェルでは機能しない可能性があります。また、スクリプトを\\
使用または起動するたびに出力されます。\\
'\'
"\\"
Bashでもこれを乱用する可能性がありますextdebug
。これは、実行中のコマンドのコンテキストに、BashのDEBUGトラップに表示されるコマンドラインを配置します。
export CMDLINE
trap 'CMDLINE=$BASH_COMMAND; true' DEBUG
shopt -s extdebug
ただし、そこにあるコマンドラインは拡張されていないため、実行すると代わりに拡張値がenv abc=$var |grep CMD
表示されます。env abc=$var
もちろん、追加の手順を実行する Bash シェルでコマンドが実行されない場合は機能しません。プロセスツリーの親にこれらのシェルがある場合は、前のCMDLINE
コマンドを実行するコマンドとして設定できます。
今、これらのトリッキーな回避策が存在しますが、スクリプトユーザーがスクリプトが最終的に実行する必要があるタスクを達成するために他の方法を使用する方が良いと驚くべきことではないかもしれません。
答え2
read
フラグを使用して呼び出すことができます-r
。
-r Backslash does not act as an
escape character. The backslash
is considered to be part of the line.
In particular, a backslash-newline pair
may not then be used as a line
continuation.
だから:
IFS="" read -r a
echo "$a"
「\」を入力すると、「\」がエコーされます。また、スペースを保存します(ターゲットでない場合はIFSビットを削除できます)。
パラメータとして渡すには、単一引用符を使用して値を変更せずに残す必要があります。
./readvar.sh '\\'
var.shを読む:
#!/bin/bash
IFS="" read -r a
./usevar.sh "$a"
var.shを使用してください。
#!/bin/bash
echo "$1"
と入力する\\
とエコーさreadvar.sh
れます。usevar.sh
\\
テキストの先頭と末尾のスペースを維持するには、IFS が必要です。