변수 목록에서 항목을 찾는 가장 좋은 방법

변수 목록에서 항목을 찾는 가장 좋은 방법

demo.cfg많은 변수를 포함하는 ""라는 파일이 있습니다 .

$VARIABLE_good="milk bread butter water"
$VARIABLE_bad="beer drugs"
$CONTENT_to_buy="Towel mouse bottle glass pen earphones"
$DUMMYVAR_mixed="drugs water bottle glass"

전체 파일에서 " drugs" 항목을 검색하고 해당 항목이 속한 항목을 식별하고 싶습니다 $VARIABLE_bad.

$VARIABLE_badas bad$VARIABLE_goodas good, $CONTENT_to_buyas to_buy, $DUMMYVAR_mixedas mixed등을 할당하고 싶습니다 .

이 파일에서 " "를 검색하면 drugs원하는 출력은 다음과 같아야 합니다.

mixed
bad

앞으로는 위와 같은 변수가 더 많아질 수 있기 때문에 이 문제를 해결할 수 있는 유연한 방법이 필요합니다.

나는 시도했다:

. demo.cfg "drugs"(이렇게 하면 모든 변수가 내보내집니다)

if [[ $(echo $DUMMYVAR_mixed | grep "drugs") ]]; then echo "mixed"; fi
if [[ $(echo $DUMMYVAR_to_buy | grep "drugs") ]]; then echo "to_buy"; fi
if [[ $(echo $VARIABLE_bad | grep "drugs") ]]; then echo "bad"; fi
if [[ $(echo $VARIABLE_good | grep "drugs") ]]; then echo "good"; fi

그러나 이는 장황해 보이고 그다지 유연해 보이지 않습니다. 더 나은 해결책이 있습니까?

답변1

이는 라인에 하나만 있는 작은 경우 awk에만 필요합니다 .=

awk -vpat=drugs -F= '$2 ~ pat {gsub(/^\$[A-Z]+_/, "", $1); print $1; }' demo.cfg

-vpat=...일치에 사용되는 변수를 구분하여 두 번째 필드의 필드와 일치시키고 -F=첫 번째 필드의 초기 부분을 빈 문자열로 바꿉니다. 그런 다음 첫 번째 필드를 인쇄합니다. (처음 부분 밑줄 앞에는 대문자만 있는 것으로 가정합니다.)=$2 ~gsub$1


값에 등호가 포함될 수 있는 경우 다음과 같이 등호 뒤에 키워드가 오는 전체 줄을 검색할 수 있습니다.

awk -vpat=drugs -F= '$0 ~ ("=.*" pat) {gsub(/^\$[A-Z]+_/, "", $1); print $1; }' demo.cfg

아니면 두 부분을 수동으로 분할하면 시간이 조금 길어집니다.


demo.cfg와 같은 달러 기호가 있는 할당을 포함 하면 $VARIABLE_good="milk bread butter water"셸에서 해당 할당을 가져올 수 없습니다.

$ . demo.cfg
-bash: =milk bread butter water: command not found

할당에는 변수 이름만 사용되며 달러 기호는 변수 확장 시에만 사용됩니다.

답변2

이것이 모든 변수의 모습이라면 다음과 같이 sum을 함께 사용할 수 있습니다 grep.sed

cat demo.cfg 
$VARIABLE_good="milk bread butter water"
$VARIABLE_bad="beer drugs"
$CONTENT_to_buy="Towel mouse bottle glass pen earphones"
$DUMMYVAR_mixed="drugs water bottle glass"


grep drugs demo.cfg | sed -r 's/.*_([a-z].*)=.*/\1/'
bad
mixed

첫 번째 grep은 단어를 검색한 후 drugs다음 표현식을 사용하여 행을 파이프합니다.sed

.*_=는 첫 번째 밑줄 앞에 있는 모든 문자를 제거합니다.
([a-z].*)== = 기호까지 소문자 저장
.*= 나머지 문자열 제거
\1= 저장된 표현식으로 대체

답변3

여기서는 다음을 사용 합니다 sed.

$ sed -n 's/^$[^_=]*_\([^=]*\)=.*drugs.*/\1/p' < file
bad
mixed

-ns명령 플래그와 결합하면 p성공적인 대체 결과만 인쇄할 수 있습니다.

GNU 사용 grep:

$ grep -Po '^[^=]*?_\K.*?(?==.*drugs)' < file
bad
mixed

drugs하나 만들고 싶다면바꾸다, 그러면 다음을 사용할 수 있습니다.

string=drugs
grep -Po "^[^=]*?_\K.*?(?==.*$string)" < file

그러나 $string정규식에 특수 문자를 포함하는 경우( -PPerl 호환 정규식 사용) 특수 문자를 이스케이프해야 합니다(예를 들어 with는 다음을 string="..."포함하는 것이 아니라 최소 3자를 포함하는 값과 일치합니다). )을 포함합니다 .... 동등한 상황은 더 나쁩니다. 이스케이프에 실패하면 명령 주입 취약점이 발생하기 sed때문 입니다(콘텐츠가 완전히 제어되지 않는 경우).awk$string

이를 통해 awk다음을 수행할 수 있습니다.

export STRING=drugs
awk -F = '(n = index($0, "=")) && \
          (m = index($0, "_")) < n && \
          index(substr($0, n+1), ENVIRON["STRING"]) {
            print substr($0, m + 1, n - m - 1)
          }' < file

관련 정보