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_bad
as bad
및 $VARIABLE_good
as good
, $CONTENT_to_buy
as to_buy
, $DUMMYVAR_mixed
as 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
-n
s
명령 플래그와 결합하면 p
성공적인 대체 결과만 인쇄할 수 있습니다.
GNU 사용 grep
:
$ grep -Po '^[^=]*?_\K.*?(?==.*drugs)' < file
bad
mixed
drugs
하나 만들고 싶다면바꾸다, 그러면 다음을 사용할 수 있습니다.
string=drugs
grep -Po "^[^=]*?_\K.*?(?==.*$string)" < file
그러나 $string
정규식에 특수 문자를 포함하는 경우( -P
Perl 호환 정규식 사용) 특수 문자를 이스케이프해야 합니다(예를 들어 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