sed는 스크립트에서 내 BASH 변수를 확장하지 않습니다.

sed는 스크립트에서 내 BASH 변수를 확장하지 않습니다.

파일에 대한 상대 또는 절대 경로를 묻는 메시지를 표시한 다음 공백을 바꾸는 스크립트가 있습니다.''그리고'\'Linux 콘솔에서 작동합니다. 교체는 첫 번째를 사용하여 수행됩니다.sed주문하다. 내 교체 후에코경로는 단지 확인용이므로 정확합니다.

그럼 두 번째sed이 명령은 내가 절대 경로를 작성한 파일을 처리해야 합니다. 글쎄, 그것은 작동하지 않을 것입니다 ... 두 번째 명령과 같습니다.$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

즉, 쉘은 하나의 매개변수가 아닌 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 시리즈 함수 중 하나를 호출합니다. X[[ :숫자:]])[[:번호:]](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)"

관련 정보