매개변수 확장 `${parameter#word}`가 예상대로 작동하지 않습니다.

매개변수 확장 `${parameter#word}`가 예상대로 작동하지 않습니다.

저는 현재 매개변수 확장, 특히 패턴 일치를 통해 매개변수 값의 일부를 제거할 수 있는 다양한 형식을 이해하려고 노력하고 있습니다. 이 문제를 해결하려면 먼저 확장에 중점을 두겠습니다 ${parameter#word}.

매뉴얼의 두 관련 섹션( man bash)(강조):

${parameter#word}
${parameter##word}
일치하는 접두사 패턴을 삭제합니다. 이것단어가 확장되어 다음과 같은 패턴을 생성합니다.경로명 확장,아래 패턴 일치에 설명된 규칙을 사용하여 매개변수의 확장된 값을 일치시킵니다. 패턴이 매개변수 값의 시작 부분과 일치하는 경우 확장 결과는 가장 짧은 일치 패턴(case '#') 또는 가장 긴 일치 패턴( '##'case)이 제거된 매개변수의 확장된 값입니다. [...]

경로명 확장
단어 분할 후 bash는 -f 옵션이 설정되지 않은 한 각 단어에서 *, ? 및 [ 문자를 검색합니다. 이러한 문자 중 하나가 발생하면 해당 단어는 패턴으로 처리되고 패턴과 일치하는 파일 이름의 알파벳순 목록으로 대체됩니다(아래 패턴 일치 참조). [...]

그러나 터미널 세션의 다음 부분을 고려하십시오.

root@cerberus ~/scripts # mkdir test
root@cerberus ~/scripts # cd test
root@cerberus ~/scripts/test # touch foo
root@cerberus ~/scripts/test # String=foobar
root@cerberus ~/scripts/test # printf '%s\n' ${String#foo}
bar
root@cerberus ~/scripts/test # printf '%s\n' ${String#*}
foobar
root@cerberus ~/scripts/test #

마지막 명령 이후의 출력을 이해할 수 없습니다. 매뉴얼에 따르면, 적어도 현재 디렉토리에 있는 유일한 파일이기 때문에 *확장되어야 합니다 . 이것이 "경로 이름 확장이 패턴을 생성하는 것과 같다"는 나의 개념입니다.foofoo

따라서 이 경우에는 다음과 printf '%s\n' ${String#*}동일한 출력을 제공해야 합니다 .printf '%s\n' ${String#foo}

분명히 이것은 사실이 아닙니다. 내 이해가 어디에서 잘못 되었습니까?

답변1

~에 대한패턴 매칭:

*빈 문자열을 포함하여 모든 문자열과 일치합니다.

그리고 부분 문자열 제거를 위한 매개변수 확장에서는 #최단 일치를 수행하고, ##가장 긴 일치를 수행한다.

이는 처음부터 빈 문자열을 제거하는 것입니다(최단 일치).

$ printf '%s\n' "${String#*}"
foobar

이렇게 하면 foobar처음부터 삭제됩니다(가장 긴 일치 항목).

$ printf '%s\n' "${String##*}"

$

설명의 마지막 단락과 관련하여: 매개변수 확장을 사용하면 현재 디렉터리의 파일에 관계없이 하위 문자열이 제거됩니다. 이 패턴은 파일이 아닌 매개변수 값과 일치하며 이를 매개변수 값에 대한 텍스트 처리 작업으로 처리합니다.

답변2

소요된다"단어"부분적으로는 패턴으로좋다파일 이름 생성에 사용되는 이름이지만 그렇지 않습니다.사용파일 이름 생성에 사용됩니다. 대신, 주어진 매개변수의 값을 일치시키기 위해 거기에 있는 패턴이 사용됩니다.

예를 들어 가 있는 경우 str=foobar시작 부분에서 패턴을 시도하고 ${str#*o}가장 짧은 일치 항목(모든 문자 수와 일치)을 찾은 다음 삭제하고 확장합니다. 마찬가지로 가장 긴 일치 항목이 발견되어 확장 시 제거됩니다.*ofoobarfo*obar${str##*o}foobar

$ str=foobar
$ echo ${str#*o}
obar
$ echo ${str##*o}
bar

왜냐하면"단어확장"을 선택하면 확장 기능을 사용할 수 있습니다.단어” 섹션은 다음과 같습니다.

$ str=foobar
$ char=o
$ echo ${str#*$char}
obar

또는

$ pat="*o"
$ echo ${str#$pat}
obar

그런 다음 위와 같이 따옴표 없이 확장하면 접두사를 제거한 후의 결과는 단어 분리 및 와일드카드를 거치게 됩니다. "${str#*o}"이를 방지하려면 전체 확장명을 인용해야 합니다.

관련 정보