2016-06-16 2 views
0

나는 몇 가지 작업을 자동화하기 위해 bash 스크립트를 작성하고있다. 필자가해야 할 일 중 하나는 디렉토리의 파일 이름 중에서 패턴을 검색 한 다음 결과를 반복하는 것입니다. 나는이 스크립트를 실행하면ls | grep with variable with regex

는 : - 확장 .ext$A_PATH_VAR/에 파일 이름들 사이에서 발견 된 모든 일치 목록

data=$(ls $A_PATH_VAR/*.ext | grep -o '201601[0-9]\{2\}\|201602[0-9]\{2\}') 
echo $data 

을 나는 예상 결과를 얻을. 그러나, 나는 저장할 때 변수에 패턴 말했다 다음과 같이 사용 :

startmo=201601 
endmo=201602 

mo=$((startmo+1)) 
grepstr="'$startmo[0-9]\{2\}" 

while [ $mo -le $endmo ] 
do 
    grepstr="$grepstr\|$mo[0-9]\{2\}" 
    mo=$((mo+1)) 
done 

grepstr="$grepstr'" 

echo $grepstr # correct 

data=$(ls $A_PATH_VAR/*.ext | grep -o $grepstr) 
echo $data 

$grepstr의 패턴이 올바르게 에코됩니다 - 즉,이 값 '201601[0-9]\{2\}\|201602[0-9]\{2\}' 포함되어 있지만 $data는 비어 있습니다. 왜 이런거야?


내 솔루션 : 아래에서

mo=$((startmo+1)) 
grepstr="($startmo[0-9][0-9]" 

while [ $mo -le $endmo ] 
do 
    grepstr="$grepstr|$mo[0-9][0-9]" 
    mo=$((mo+1)) 
done 

grepstr="$grepstr)" 

files=$(ls $A_PATH_VAR/*.ext) 

setopt shwordsplit 

for file in $files 
do 
    if [[ $file =~ $grepstr ]] 
    then 
    date=$BASH_REMATCH 
    fi 

    ... 
done 
+4

'패턴 = " '패턴'"'패턴 = 'pattern'''하고 당신은 grepping해서는 안 어디에 – anubhava

+0

당신은 모든 당신의 변수를 인용해야한다 'ls' 출력은로 시작합니다. http://mywiki.wooledge.org/ParsingLs –

+1

을 참조하십시오 ... 왜 문자와 구문 인용 부호를 혼합 할 수 없는지 이해하려면 http://mywiki.wooledge.org/BashFAQ/050 –

답변

6

, 나는 (입력 소스가이 오프닝 참고 ls should not be used in this manner 넘어, ls 것을 무시하고, find있어하는 GNU 확장 된 형태로, 대신 -regex 연산자 포함)를 고려해야합니다. 에서


:

pattern="'pattern'" 
grep $pattern 

... 따옴표 ("는) 구문 - 그들은 작은 따옴표 반면, 내부, 그 구문 분석 단계에서 쉘에 의해 소비있어 그것들은 리터럴입니다. - 내부의 모든 것이 문자열의 일부로 간주되도록 외부 구문 쿼리를 지정합니다 (큰 따옴표로 묶인 내용을 분석하는 규칙이 다른 경우 제외). 당신이 grep $pattern을 실행할 때

따라서, 다음과 같은 상황이 발생합니다 $pattern

  • 내용은 IFS 내에서 모든 문자에 단어로 분리된다. 기본적으로 IFS에는 공백 만 포함됩니다. 그러나 IFS=a이 있다면이 단어는 "pa이라는 단어와 단어로 구분됩니다. ttern"
  • 이러한 단어는 각각 glob로 확장됩니다. 따라서 pattern에 이 포함되어 있고 공백에서 IFS 구문 분석의 기본값을 사용하는 경우 "hello, *world"-으로 바뀌었을 것이고 *은 다음과 같은 파일 목록으로 대체 될 것입니다. 현재 디렉토리.

분명히, 당신은 이것을 원하지 않습니다.나는이 작업을 한 경우 다음과 같이 BTW

pattern="pattern" 
grep "$pattern" 

가, 내가 손으로 할 필요 피하기 위해 [을 작성할 수 있습니다 : 당신의 목표는 문자열 분할 및 글로브 확장을 방지하기 위해 경우에 따라서 만 구문 따옴표를 사용 각각의 가능한 날짜 범위에 대한 정규식] 건설 :

startmo=201601 
endmo=201705 
currmo=$startmo 

# this requires GNU date 
# on MacOS, you can install this via macports and invoke it as gdate 
next_month() { 
    date -d "+1 month ${1:0:4}-${1:4:2}-15" +%Y%m 
} 

while [[ $currmo <= $endmo ]]; do 
    currmo=$(next_month "$currmo") 
    files=(*"$currmo"*) 
    [[ -e $files ]] || { echo "No files found for month $currmo" >&2; continue; } 
    printf '%s\n' "${files[@]}" 
done 
+0

이 답변에 재 대결 연산자를 사용하는 것에 대한 귀하의 의견을 포함시켜야한다고 생각합니다. 나는 grep을 피하고 그것을 대신 사용하여 수행 할 작업을 수행 할 수있었습니다. – NmdMystery

+0

귀하의 질문이 당신이 그 라인을 따라 정말 좋은 대답을 할 수 있도록 충분히 자세하게 설명했는지 확신 할 수 없습니다. 리터럴 패턴을''패턴 "'플레이스 홀더, 패턴과 일치하는 파일 이름의 예제 및 원하는 출력 예제와 함께 포함 시키면 그렇게하는 것이 더 쉬울 것입니다. –

+0

좀 더 구체적으로 코드를 업데이트했습니다. – NmdMystery