echo \\* - bash 백슬래시 이스케이프 동작, 거꾸로 평가됩니까?

echo \\* - bash 백슬래시 이스케이프 동작, 거꾸로 평가됩니까?

그래서 내가 할 때 bash에서

echo \*
*

*가 이스케이프되어 문자 그대로 사용되므로 이는 올바른 것 같습니다.

그런데 그렇게 하면 이해가 안 돼요.

echo \\*
\*

첫 번째 백슬래시가 두 번째 백슬래시를 이스케이프한다고 생각하므로 두 개의 백슬래시 "\\"는 문자 그대로 "\"를 제공합니다. 다음 *에는 특별한 의미가 있습니다. 나는 그것을 기대합니다:

echo \\*
\file1 file2 file3

답변 요약: \는 문자 그대로 사용되므로 문자 "a"로 시작하는 파일을 찾은 echo \*것처럼 동작합니다 .echo a*

후속 질문, 정확히 동일하게 인쇄하려면

\file1 file2 file3

어떤 명령을 사용해야 합니까? 예를 들어 아래와 같이 하는데 공간이 필요하지 않습니다.

echo \\ * 
\ file1 file2 file3

답변1

이는 현재 디렉터리에 백슬래시로 시작하는 이름을 가진 파일이 없는 경우 예상되는 동작입니다. 불다*기존 파일 이름과 일치하도록 확장되지만:

패턴이 기존 파일 이름이나 경로 이름과 일치하지 않는 경우 패턴 문자열은 변경되지 않은 상태로 유지되어야 합니다.

로 시작하는 파일 이름이 없으므로 \패턴은 그대로 두고 echo매개변수를 지정합니다 \*. 이 동작은 종종 혼란스럽고 일부 다른 쉘(예 zsh: . 너이는 Bash에서 다음 명령을 사용하여 변경할 수 있습니다.shopt -o failglob, 그러면 오류가 발생 zsh하고 오작동보다는 문제를 진단하는 데 도움이 됩니다.

*및 패턴 문자는 ?단어의 어느 위치에나 나타날 수 있으며 앞과 뒤의 문자는 문자 그대로 일치합니다. 그렇기 때문에 서로 다른 출력을 echo \\*제공 echo \\ *합니다. 첫 번째는 다음으로 시작하는 모든 항목과 일치하고 \(실패함) 두 번째는 a 를 출력한 \다음 모든 파일 이름을 출력합니다.


아마도 원하는 출력을 안전하게 얻는 가장 간단한 방법은 다음을 사용하는 것입니다.인쇄 기능:

printf '\\'; printf "%s " *

echo *-어쨌든 특이한 파일 이름이 포함되어 있으면 안전하지 않습니다 \.

답변2

이 시도:

printf "\\%s" "$(echo *)"

설명하다:

  • printf형식 인수와 형식 문자열로 대체될 0개 이상의 인수를 허용합니다.
  • \\형식의 의미는 형식과 동일합니다.echo \\
  • %s다음 인수를 가져와 결과에 대체함을 나타냅니다.
  • "$(echo *)"의미: echo *결과를 실행하고 단일 매개변수에 넣습니다 printf. 작동 원리로 인해 printf매개변수에 넣어야 합니다.

답변3

노력하다...

set file*
printf %s\  "\\$@"

배열의 헤드에 백슬래시를 추가하므로 첫 번째 요소만 추가됩니다. 엔딩도 똑같이 하시면 됩니다. 다음과 같이 백슬래시로 모두 구분할 수 있습니다 \\.

printf \\%s file*

...또는...

set file*; IFS=\\; printf %s\\n "$*"

답변4

나는 질문의 후반부("어떤 명령을 사용해야 합니까?")에 대한 다른 모든 대답은 기술적으로나 극단적인 경우에도 잘못되었다고 생각합니다. 나는 이것이 다른 답변의 문제를 해결한다고 믿습니다.

(set -- *; echo "\\$*")


그리고 (FWIW) 모든 쓰기는 ( 와 달리 ) 단일 명령으로 수행됩니다 printf '\\'; printf "%s " *; echo.

  • 서브쉘을 사용하면 외부 범위/컨텍스트에서 위치 매개변수 설정/변경을 피할 수 있습니다.
  • 간단하게 set *위치 매개변수( $1, 등) $2$3현재 디렉터리의 파일 이름으로 설정합니다. (파일 이름은.dotglob(점)은 이 옵션 설정 여부에 따라 포함됩니다 . )
  • set *이름이 다음으로 시작하는 파일이 있으면 실패할 수 있습니다.-*(대시) ( 목록의 첫 번째 파일  입니다 ). set -- *이것을 처리하십시오. --"이 이후의 모든 내용은 옵션/플래그가 아니라 매개변수입니다."라고 말합니다.
  • $*$1 $2 $3 …공백으로 구분된 위치 매개변수( )의 목록입니다 . 이유는 (질문의 예제 명령)과 같이 줄 시작 부분에 출력 \\되지만 뒤따르는 내용을 방해하지는 않습니다 .\echo \\ *$*
  • $*위치 매개변수 목록( $1 $2 $3 …)입니다. 매개변수는 첫 번째 문자로 구분됩니다.$IFS. 의 첫 번째 문자가 $IFS공백이 아닐 수 있는 경우 다음을 수행하십시오.
(set -- *; IFS=" "; echo "\\$*")

약간 더 자세한 옵션은 다음과 같습니다.

(set -- *; printf "%s\n" "\\$*")

그리고

(set -- *; printf "\\%s\n" "$*")

echo이는 옵션 없이도 매개변수 문자열의 백슬래시가 해석될 수 있는 환경에서 더 안전합니다 -e.

다시 말하지만, IFS=" ";의 첫 번째 문자가 $IFS공백이 아닐 수 있으면 추가하세요.

관련 정보