문자열 배열 내에 문자열이 존재하는지 테스트

문자열 배열 내에 문자열이 존재하는지 테스트

파일에 있는 모든 줄의 처음 3글자를 (cut을 사용하여 가져옴) 배열 내부의 문자열과 비교하는 스크립트를 작성 중입니다. 이미 둘러봤지만 찾은 솔루션이 내 시스템에서 작동하지 않았습니다.

지금은 다음과 같습니다.

weekdays=([Mon]=1 [Tue]=1 [Wed]=1 [Thu]=1 [Fri]=1 [Sat]=1 [Sun]=1)
input="/Foo/Bar.log"

while read -r line
do

cutline="$(echo ${line} | cut -c 1-3"

if [[ ${weekdays["$cutline"]} ]]
then
echo "Match"
else
echo "No Match"
fi

done < ${input}

라인은 제대로 잘렸지만 처음 3개의 문자가 무엇이든 "일치"를 반환하기 때문에 테스트 중에 무언가가 거짓 긍정을 반환합니다.

-x를 사용하여 스크립트를 확인했을 때 대신 사용된 실제 테스트 대신 표시되었습니다.

[[ -n 1 ]]

그리고 표현식으로 테스트했을 때 [ ]다음과 같은 결과가 나타났습니다.1

전체 단어뿐만 아니라 배열의 모든 단일 문자를 확인합니까, 아니면 다른 문제가 있습니까?

문제가 없으면 다음 줄을 계속하기 전에 줄의 처음 3글자를 배열 내부의 모든 문자와 비교하는 다른 방법이 있습니까?

참고로 저는 실제로 Bash 4를 실행하고 있으므로 연관 배열이 작동해야 합니다.

답변1

기본적인 오류는 실제로 연관 배열을 선언하지 않는다는 것입니다.

$ weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)
$ echo ${weekdays[@]}
1
$ echo ${weekdays[0]}
1
$ echo ${weekdays[2]}

$

나는 bash가 그것을 어떻게 처리하는지, 왜 그것이 단지 a를 취하는지 완전히 확신하지 못하지만 1그것이 연관 배열이 아니라고 확신합니다. man bash(강조) 에 설명된 대로 :

name[subscript]=value 구문을 사용하여 변수를 할당하면 인덱스 배열이 자동으로 생성됩니다. 아래 첨자는 숫자로 평가되어야 하는 산술 표현식으로 처리됩니다. 인덱스 배열을 명시적으로 선언하려면 선언 -a 이름을 사용하십시오(아래 SHELL BUILTIN 명령 참조). 선언 -a 이름[subscript]도 허용됩니다. 하위 스크립트는 무시됩니다.

연관 배열은 선언 -A 이름을 사용하여 생성됩니다.

따라서 대신 이것을 시도해 보면 예상대로 작동할 것입니다.

declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)

즉, 스크립트는 필요한 것보다 조금 더 복잡합니다. 동일한 접근 방식을 사용하는 더 간단한 버전은 다음과 같습니다.

#!/bin/bash
declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)
input="/Foo/Bar.log"

cut -c 1-3 "$input" | while read -r line; do
    if [[ ${weekdays["$line"]} ]]
    then
            echo "Match : $cutline : ${weekdays[$line]}"
    else
            echo "No Match"
    fi
done    

아마도 다음과 같이 할 것입니다.

#!/bin/bash
cut -c 1-3 "$1" | while read -r line; do
        case $line in
        "Mon"|"Tue"|"Wed"|"Thu"|"Fri"|"Sat"|"Sun")
                        echo yes;;
                *)
                        echo no;;
        esac
done

그런 다음 대상 파일 이름을 인수로 사용하여 스크립트를 실행합니다.

script.sh /Foo/Bar.log"

답변2

텍스트 처리 도구를 한 번 호출하여 텍스트를 처리하겠습니다., 각 입력 줄에 대한 여러 도구가 아닙니다.

awk -v 'weekday=(Mon|Tue|Wed|Thu|Fri|Sat|Sun)' '
  {print ($0 ~ "^" weekday ? "" : "No ") "Match"}' < "$input"

입력의 각 줄에 대해 특정 응용 프로그램을 실행해야 하는 경우 루프를 사용하지만, 줄을 일부 파일로 출력하는 것과 같은 텍스트 처리일 경우에는 다음 awk과 같이 수행할 수 있습니다.

awk -v 'weekday=Mon|Tue|Wed|Thu|Fri|Sat|Sun' '
  (day = substr($0, 1, 3)) ~ weekday {
    print substr($0, 4) > day ".txt"
  } < "$input"

관련 정보