sedはスクリプト内の私のBASH変数を拡張しません。

sedはスクリプト内の私のBASH変数を拡張しません。

ファイルへの相対パスまたは絶対パスを求めるプロンプトが表示され、スペースを置き換えるスクリプトがあります。''そして「\」Linuxコンソールで動作します。交換は最初のものを使用して行われます。sed注文する。私の交換後エコパスは単に確認用なので正確です。

それから2番目sedこのコマンドは、私が絶対パスを作成したファイルを処理する必要があります。まあ、それはうまくいきません... 2番目のコマンドのようなものです。$drill_file拡張はありません。最も奇妙なことは、スクリプトの外でもうまく拡張されていることです...うわー! ?

#!/bin/bash

echo "Give relative or absolute path to the \"drill.TXT\" file:"

read drill_file_temp
drill_file=$(echo $drill_file_temp | sed -r 's/\s/\\ /g')
echo $drill_file

sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' $drill_file

echo "Conversion finished."

答え1

文字列に引用符を入れます。問題は、パラメータ拡張後に引用符付き文字が解析されないことです。希望の効果を得るために必要

eval sed ... $drill_file

set -x以下を使用して、シェルがコマンドラインをどのように表示するかを確認できます。

> text=a\\\ \\\ \\\ b
> echo $text
a\ \ \ b
> set -x
> : $text
+ : 'a\' '\' '\' b

つまり、シェルは1つのパラメータではなく4つのパラメータを表示します。

他の人が言ったように、$drill_file/を引用する必要があります$drill_file_temp"$drill_file"

答え2

変数を参照する場合は、最初のsedを実行する必要はありません。

read -p "Give relative or absolute path to the \"drill.TXT\" file: " drill_file
if [[ -f "$drill_file" ]]; then
    sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' "$drill_file"
    echo "Conversion finished."
else
    echo "no such file: '$drill_file'"
fi

答え3

カーネルは\(バックスラッシュ)を理解していません。
'file \ with \ space'の場合、drill_filesedはとして実行されます
sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' file\ with\ space
まず、シェルはそれ自体を複製し、 argv[0]=sed, argv[1]=s/(^ パラメータを渡して execl シリーズ関数の 1 つを呼び出します。 X[[ :number:]])[[:番号:]](Y[[:番号:]])[[:番号:]]/\1\2/, argv[2]=file\, argv[3]=with\ および argv[4]=space. execl はシェルの代わりに sed を使用します。 sedが起動し始めたら、「with \」と「space」を呼び出してopen("file\ ",O_RDONLY)同じことを行います。カーネルは要求を関連する fs に渡します。 FsがENOENTを返すということは、fsにそのようなエントリがないことを意味します。そのようなファイルが実際に存在しないので、それは本当です。 sed はエラーを受け取り、エラーメッセージを表示します。

$drill_fileを参照すると、sedで取得したファイル名は 'file\with\space'なので、今回は開くことができません。

eval sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' "$drill_file"
evalは引数を解析し、コマンドをビルドし、ビルドされたコマンドを実行します。壊して修復するのは冗長で複雑です。

\(バックスラッシュ)エスケープは、シェルが実行されている場合にのみ適用されます。sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/'$drill_file_temp「効果があるんです。
これも効果があります。

sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' \
"$(read -p "Give relative or absolute path to the \"drill.TXT\" file: " \
drill_file_temp;echo $drill_file_temp)"

関連情報