
単純なbashパーサーを作成しようとしています。私はこのステップに従いますウィキペディア。私が仮定したことの1つは、文字を正しくエスケープすることで、入力文字列全体を繰り返すことで一重引用符と二重引用符の両方を削除できることでした。 Bashで実行すると、これら2つの文字列は同じ出力を生成する必要があります。
私のパーサのこの部分は与えられた文字列を取得し、一重引用符と二重引用符を削除します(エスケープされてリテラルとして解釈される引用符を除く)。 Bashで実行すると、両方の文字列はまだ同じ結果を生成する必要があります。
マイパーサーは、次のように生のコンテンツをマイパーサーに変換します。しかし、オリジナルは動作しますが、My Parseは動作しません。
# Original
$ node -p "console.log($(echo \"hello world\"))"
hello world
# My Parse: Escape everything within double quotes except command substitution
v v
$ node -p \c\o\n\s\o\l\e\.\l\o\g\($(echo \"hello world\")\)
[eval]:1
console.log("hello
^^^^^^
SyntaxError: Invalid or unexpected token
解析エラーの原因についていくつかのアイデアがあります。
二重引用符内のコマンド置換がどのように機能するかについていくつかの基本的な側面を理解していません。私の理解は、コマンド置換が最初に発生し、次に引用符が処理されることです。
コマンド置換が実際にどのように出力されるかについてのいくつかの基本的な側面を理解していません。私の理解は、コマンドではなく
$(echo \"hello world\")
文字列を生成する必要があるということです。"hello world"
"hello
world"
このコマンドにはいくつかの特徴があります
echo
(おそらく変更可能だからです)。実際に運が良かったので、元のシナリオでは動作しましたが、実際にはコマンドの置き換えからコマンドを変更すると問題が発生する可能性があります。ノード/JavaScriptに問題があります。これは非常に単純なjsなので、それはすべてだとは思わない...
最後に興味深いのは、コマンド置換を二重引用符で囲むときに機能することです。たぶん、質問全体を異なって尋ねるかもしれません。二重引用符(エスケープされた部分は含まれていません)なしで、以下のような入力をどのように作成できますか?
# Escape everything but keep command substitution in double quotes
v v
$ node -p \c\o\n\s\o\l\e\.\l\o\g\("$(echo \"hello world\")"\)
hello world
注:この質問は少し後続の質問です。二重引用符エスケープに関するこの質問
答え1
これは噴射行動中。始める前に注意深くお読みください。シェル拡張実行される順序に注意してください。
見ているnode -p "console.log($(echo \"hello world\"))"
拡張をサポートしていますか?いいえ
チルダ拡張?いいえ
パラメータ拡張?ここではない
コマンドの置き換え?うん、任せてください。
node -p "console.log("hello world")"
算術拡張?いいえ
プロセスの交換?いいえ
噴射?パラメータは
-p
引用符で囲まれているため、そうではありません。ファイル名拡張子?いいえ
見積もりの削除完了
node
bashは2つのパラメータを生成して渡します-p
。console.log("hello world")
今見てnode -p console.log($(echo \"hello world\"))
コマンドの交換後、私たちは
node -p console.log("hello world")
単語分割を実行するとき、to引数には
-p
それを保護する引用符はありません。現在のコマンドの場合、bashには4つのフラグがあります。node -p console.log("hello world") ^^^^ ^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^
bashはnode
これによって生成されます。サム引数:-p
と - は明らかにJavaScript構文エラーですconsole.log("hello
。何が起こるのか見てみましょう。world")
console.log("hello
詳細については、次を参照してください。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク
答え2
あなたの例では、「node -p」が何をすべきかわかりません。ただし、例を再現しようとすると、次のような結果が得られます。
[user@c0n1 ~]# echo "hello world"
hello world
[user@c0n1 ~]# echo $(\"hello world\")
-bash: "hello: command not found
最後の例の空白は引用符の中の文字列を分離し、&bashは "hello"がコマンドだと思います。バックスラッシュでスペースを保護すると、次の説明が確認されます。
[user@c0n1 ~]# echo $(\"hello\ world\")
-bash: "hello world": command not found
コマンド置換で文字列を生成する場合は、次のコマンドが必要です。
[user@c0n1 ~]# echo $(echo \"hello world\")
"hello world"
答え3
回答紙:@glen-jackmanの答えは素晴らしく、私にインスピレーションを与えました。
私のbashスクリプトは次のとおりです。
cmds="git commit -m \"$(date)\""
echo $cmds
$cmds
スクリプトを実行すると、次の結果が表示されます。
git commit -m "Fri Jan 13 10:27:05 CST 2023"
error: pathspec 'Jan' did not match any file(s) known to git
error: pathspec '13' did not match any file(s) known to git
error: pathspec '10:27:05' did not match any file(s) known to git
error: pathspec 'CST' did not match any file(s) known to git
error: pathspec '2023"' did not match any file(s) known to git
set -x
スクリプトをデバッグするために、次のようになりました。
++ date
+ cmds='git commit -m "Fri Jan 13 10:34:30 CST 2023"'
+ echo git commit -m '"Fri' Jan 13 10:34:30 CST '2023"'
git commit -m "Fri Jan 13 10:34:30 CST 2023"
+ git commit -m '"Fri' Jan 13 10:34:30 CST '2023"'
error: pathspec 'Jan' did not match any file(s) known to git
error: pathspec '13' did not match any file(s) known to git
error: pathspec '10:34:30' did not match any file(s) known to git
error: pathspec 'CST' did not match any file(s) known to git
error: pathspec '2023"' did not match any file(s) known to git
実際に実行するコマンドは次のとおりです。git commit -m '"金曜日' 1月13日 10:34:30 CST '2023"'しかし、私が期待しているのはgit commit -m "2023年1月13日金曜日10:34:30 CST"。
これは噴射行動中
eval
私の解決策は、次のように変更されたスクリプトを使用することでした。
cmds="git commit -m \"$(date)\""
echo $cmds
eval $cmds
動作し、出力は次のようになります。
++ date
+ cmds='git commit -m "Fri Jan 13 10:43:56 CST 2023"'
+ echo git commit -m '"Fri' Jan 13 10:43:56 CST '2023"'
git commit -m "Fri Jan 13 10:43:56 CST 2023"
+ eval git commit -m '"Fri' Jan 13 10:43:56 CST '2023"'
++ git commit -m 'Fri Jan 13 10:43:56 CST 2023'
[main b76daa9] Fri Jan 13 10:43:56 CST 2023
2 files changed, 21 insertions(+), 22 deletions(-)