동적 사례 설명 생성

동적 사례 설명 생성

다소 긴 사례 설명이 있습니다(일치할 패턴이 약 150개임).

case "$line" in
  pattern1) ret=result1;;
  pattern2) ret=result2;;
  pattern3) ret=result3;;
   ...
   ...
esac

그러나 스키마는 실제로 사용자가 수정할 수 있는 데이터이므로 이는 적절하지 않습니다. 그래서 새로운 패턴이 필요할 때마다 Case문을 수정해야 합니다.

내가하고 싶은 것은 다음과 같은 별도의 텍스트 파일을 만드는 것입니다.

pattern1=result1
pattern2=result2
pattern3=result3
...
...

텍스트 파일을 읽고 사례 설명을 만드는 데 사용됩니다. 이는 새로운 패턴이 필요할 때마다 코드를 수정할 필요가 없다는 장점이 있습니다.

텍스트 파일의 입력을 기반으로 사례문을 자동으로 생성하는 방법이 있습니까? 다른 옵션도 열려 있지만 아직 일치시킬 입력 라인이 많기 때문에 입력 라인을 매우 빠르게 패턴 일치시킬 수 있는 솔루션을 찾고 있습니다.

답변1

동적 사례 설명 생성은 다소 이상한 일이지만... 그렇습니다. 가능합니다.

나는 아래와 같이 할 것입니다. (내가 탐색했다면모두내가 생각할 수 있는 다른 방법은 다음과 같습니다.

. <( awk -F= 'BEGIN { print "case \"$line\" in" }
                    { print $1 ") ret=" $2 ";;" }
              END   { print "esac" }' patternfile )

patternfile다음을 포함하는 경우

pattern1=result1
pattern2=result2
pattern3=result3

명령 awk자체가 출력됩니다.

case "$line" in
pattern1) ret=result1;;
pattern2) ret=result2;;
pattern3) ret=result3;;
esac

. <( awk ... )구성을 사용하면 마치 스크립트 파일에 대소문자 스위치를 직접 작성하는 것처럼 스크립트에 소스가 입력됩니다.


이것은 쉘 스크립트의 "동적 사례 설명 생성"에 대한 답변입니다. 하지만, 당신이 할 계획이기 때문에루프 내에서, 위의 접근 방식은 매우 나쁜 접근 방식입니다. awk10,000번 실행하게 되어 patternfile가능한 성능 이점보다 더 중요해지기 때문입니다.

대신 케이스 스위치를 생성하는 코드 생성기를 작성하는 것이 좋습니다.함수 정의 내에서—전체 함수 정의를 생성하고 가져옵니다. 즉, 다음과 같습니다.

# At the top of your script file:
. <( awk -F= 'BEGIN { print "my_case_switch_function() {"
                      print "case \"$1\" in" }
                    { print $1 ") ret=" $2 ";;" }
              END   { print "esac"
                      print "}"   }' patternfile )

# Within your while loop (or wherever else you want):
my_case_switch_function "$line"

case이렇게 하면 결과 스위치를 한 번만 처리한 후 반복해서(원하는 경우 최대 10,000회) 재사용할 수 있습니다 patternfile. 따라서 성능은 patternfile수동으로 대소문자 스위치를 생성하고 이를 스크립트에 하드코딩한 것과 같습니다( awk150줄 파일에서 한 번 실행하는 작은 오버헤드를 제외하면 10,000줄 파일을 처리하는 것과 비교하면 무시할 수 있습니다).


그러나 다시 강조해야 할 점은 쉘 스크립트 케이스 스위치는 다음과 같습니다.아니요10,000줄의 파일을 한 줄씩 처리하는 도구입니다. 따라서 이 솔루션은 케이스 스위치를 하드코딩하여 얻을 수 있는 성능에 매우 가깝지만 여전히 느릴 수 있습니다.

견적으로 이동스티븐 차제라스:

앞서 언급했듯이 명령을 실행하는 데는 비용이 듭니다. 명령어가 내장되어 있지 않으면 비용이 엄청나지만, 내장되어 있어도 비용이 엄청납니다.

쉘은 이러한 방식으로 작동하도록 설계되지 않았으며 고성능 프로그래밍 언어라고 주장하지도 않습니다. 그들은 아닙니다. 그들은 단지 명령줄 해석기일 뿐입니다. 따라서 이와 관련하여 최적화가 거의 이루어지지 않았습니다.

답변2

내 생각에 이것은 XY질문. 실제로 동적 문을 생성할 필요는 없습니다 case. 파일을 간단한 키-값 저장소로 사용하고 싶을 뿐입니다. 한 가지 해결책은 검색 파일을 사용한 grep후 다음을 사용하여 값을 추출하는 것입니다 cut.

ret=$(grep "^$line" file.txt | cut -d = -f 2)

답변3

다음 스키마 파일을 사용하십시오.

a*c=abc
def=def

=그리고 행당 하나만 있다고 가정합니다.

#! /bin/bash

line=abc
while IFS= read -r patternline; do
        [[ $patternline =~ .=. ]] || continue
        pattern="${patternline%=*}"
        result="${patternline##*=}"
        if [[ "$line" == $pattern ]]; then
                ret="$result"
                echo "$patternline"
                break
        fi
done <patterns.txt

여러 줄을 확인해야 하는 경우 파일 내용을 배열로 읽어옵니다.

#! /bin/bash

patterns_file="patterns.txt"

patterns=()
results=()
patternindex=0


### BEGIN: init
while IFS= read -r patternline; do
        [[ $patternline =~ .=. ]] || continue
        patterns[patternindex]="${patternline%=*}"
        results[patternindex]="${patternline##*=}"
        ((patternindex++))
done <"$patterns_file"
pattern_count="$patternindex"
### END:   init

patterncheck () {
        local line="$1" i=0 pattern= result=
        for((i=0;i<pattern_count;i++)); do
                pattern="${patterns[i]}"
                result="${results[i]}"
                if [[ "$line" == $pattern ]]; then
                        ret="$result"
                        echo "$line"
                        break
                fi
        done
} # patterncheck ()

# tests

patterncheck abc
patterncheck def

관련 정보