For 루프 및 위치 지정 명령 정규식이 일치하지 않습니다.

For 루프 및 위치 지정 명령 정규식이 일치하지 않습니다.

구성을 변경할 때 접미사가 .original인 원본 파일의 복사본을 만듭니다. 이제 모든 *.original 파일을 찾고 .original 접미사가 있거나 없는 두 버전을 모두 사용하는 간단한 스크립트를 작성 중입니다.

경로 중간에 있는 문자열과 locate파일이 일치하지 않는 것을 피하기 위해 정규식과 함께 명령을 사용했습니다 .original

내 명령이 locate --regex ^.*\\.original$완벽하게 실행 되고 있습니다 in terminal. .original 접미사로 끝나는 모든 파일을 찾습니다.file.original

하지만in bash script에서 동일한 명령을 사용하면 다음과 같은 변형이 for loop반환됩니다 .file.original file-original file_original

.original 파일만 얻으려면 정규식이나 for 루프를 어떻게 수정해야 합니까?

내 껍질은 다음과 같습니다

$ echo $BASH
/usr/bin/bash

내 bash 스크립트는 다음과 같습니다

#!/usr/bin/bash
echo "Plain locate command:"
locate --regex ^.*\\.original$ | grep test

echo "For loop:"
for file in `locate --regex ^.*\\.original$ | grep test`; do
        echo $file
done 

테스트에 사용할 수 있습니다.

mkdir /tmp/test 
touch /tmp/test/file.original
touch /tmp/test/file-original
touch /tmp/test/file_original
updatedb
locate --regex ^.*\\.original$

내 터미널에서 다음을 찾습니다.

/tmp/test/file.original

하지만 내 스크립트에서는 다음을 찾습니다.

Plain locate command:
/tmp/test/file.original
For loop:
/tmp/test/file-original
/tmp/test/file.original
/tmp/test/file_original

답변1

백틱에는 더 많은 이스케이프가 필요합니다. 이것이 당신이 그것을 선호해야 하는 이유 중 하나입니다 $()(이 답변의 "백슬래시 재미" 참조:$(stuff)이들그리고 그리고 의 차이점은 무엇인가요 `stuff`?).

백틱 내에서 이스케이프 처리가 충분하지 않기 때문에 문자열이 결국 정규 표현식으로 해석될 때 이스케이프하려는 지점이 이스케이프되지 않습니다.

관련 줄을 다음과 같이 변경합니다.

for file in $(locate --regex '^.*\.original$' | grep test); do

노트:

  • 백슬래시를 편리하게 처리하기 위해 작은따옴표를 사용합니다.그리고별표. 원본 코드에서 따옴표가 없고 이스케이프 처리되지 않은 별표는 트리거될 수 있습니다.파일 이름 확장자.

  • ^.*정규식에는 아무것도 변경되지 않았습니다. 작은따옴표로 \.original$충분합니다. ^.*파일명 확장 가능성을 지적하기 위해 그대로 유지하기로 결정했습니다 .

  • 에 익숙해참조 변수(예를 들어 echo "$file"). 연결된 답변 도 인용을 제안하지만 이는 $()루프 for에서는 잘못된 것입니다 . 인용하지 않는 것도 $()실수입니다. 둘 다 틀렸기 때문에…

  • 일반적으로 말하면for이런 루프를 만드는 것은 일반적으로 실수입니다.. 이것은Bash의 첫 번째 함정. 더 나은 출력 으로 locate작업을 수행 하려면 xargsnull로 끝나는 문자열로 처리하는 것이 가장 좋습니다.

    locate -0 … | grep -z … | xargs -r0 …
    

    이러한 옵션은 이식 가능하지 않습니다.

관련 정보