2014-10-28 4 views
1

이것은 내 처음으로 여기에 게시하므로 나와 함께하시기 바랍니다.BASH Palindrome Checker

나는 배쉬 할당을 받았지만 교수는 전혀 도움이되지 않아 그의 노트도있다.

우리의 임무는 파일에서 문장을 필터링하고 출력하는 것입니다. 이 경우, 디렉토리는 다음과 같습니다

/usr/share/dict/words 

단어의 길이는 3에서 45 범위와 소문자를 (주어진 사전이 문자와 uppercases뿐만 아니라 소문자가) 필터로되어있다. 즉 "-dkas-das"이므로 "q-evvavve-q"와 같은 것이 회문으로 간주 될 수 있지만 올바른 결과로 받아 들여서는 안됩니다.

어쨌든, 나는 x 개의 단어를 걸러 낼 수 있으며 리턴 할 수 있습니다 (소문자 만 필터링하지 않음).

grep "^...$" /usr/share/dict/words | 
grep "\(.\).\1" 

그리고 나는 그렇게 5 개 글자 단어 및 7에 대한 후속 라인을 사용할 수 있습니다

grep "^.....$" /usr/share/dict/words | 
grep "\(.\)\(.\).\2\1" 

은 그러나 교수가 그것을 원하지하지 않습니다. 루프를 사용해야합니다. 나는 컨셉을 얻지 만 문법을 모른다. 내가 말했듯이, 노트는별로 도움이되지 않는다.

내가 시도한 것은 x = ...와 y = .. 변수를 설정하고 while 루프에서 x = $ x $ y를 가졌지 만 구문 오류가 발생하지 않았고 x + = ..도 않았다.

도움을 주시면 감사하겠습니다. 심지어 소문자가 아닌 문자를 걸러 냈습니다.

감사합니다.

편집 :

당신이 솔루션에 대한 해결책이나 힌트를 제공하는 경우, 가장 간단한 방법이 선호된다. 두 개의 grep 문과 루프를 사용하는 것이 좋습니다.

다시 한번 감사드립니다. 여기

답변

2

: 변수에로 사전 대부분의 읽기,

으로는 의견에서 지적

aha 
bib 
bob 
boob 
... 
wow 

업데이트 :

for word in `grep -E '^[a-z]{3,45}$' /usr/share/dict/words`; 
    do [ $word == `echo $word | rev` ] && echo $word; 
done; 

출력 내 사전을 사용 for 루프가 가장 효율적이지 않을 수 있으며 일부 셸에서는 오류를 유발할 위험이 있습니다. 다음은 업데이트 된 버전입니다.

grep -E '^[a-z]{3,45}$' /usr/share/dict/words | while read -r word; 
    do [ $word == `echo $word | rev` ] && echo $word; 
done; 
+0

좋아, 작동하지만 나에게 단어 목록이 표시되고 모든 단어에 대해 ENTER를 눌러야합니다. 그것이 자격이된다면 나타나고 그렇지 않다면 공란으로 남을 것입니다. 또한 grep을 사용해야하지만 여전히 감사합니다. – Greg

+0

모든 메아리가 끝난 후 Enter 키를 눌러야 이상합니다. 그냥 느린가요? 내 솔루션에서'grep'을 사용하고 있습니다 :'egrep'은'grep -E'와 같습니다. –

+0

흠, 아직 입력해야 할 일을하고 있습니다. 기억한다면, 처음 복사했을 때 작동했지만 추락했습니다. 차이가 나는 경우 퍼티를 사용하고 있습니다. – Greg

0

확인 당신이 시작하는 무언가이다 "."

나는 단지의 번호를 생성, 위 가지고 계획을 사용하는 것이 좋습니다 for 루프를 사용합니다.

이 질문은 3 ~ 45에서 루프를 만드는 방법을 설명합니다 : "."

How do I iterate over a range of numbers defined by variables in Bash?

for i in {3..45}; 
do 
    * put your code above here * 
done 

지금 당신은 그냥 "나"점의 수를 만드는 방법을 알아 내야 첫 번째 grep에서 완료되었습니다.

또한 sed를 살펴보면, 소문자가 아닌 답변을 누설 할 수 있습니다.이처럼

+0

네, 감사합니다. 나는 어딘가에 나를 데려 갈 것 같은 느낌. – Greg

2

grep은 낭비입니다. 당신은 단순히 일거에

grep -E '^([a-z])[a-z]\1$' /usr/share/dict/words 

을, 마찬가지로,이 같은 grep의 표준 입력에 식을 넣을 수 있습니다 :

echo '^([a-z])[a-z]\1$ 
^([a-z])([a-z])\2\1$ 
^([a-z])([a-z])[a-z]\2\1$' | grep -E -f - /usr/share/dict/words 

그러나, 일반 grep\9 넘어 역 참조를 허용하지 않습니다. grep -P을 사용하면 두 자릿수 역 참조도 사용할 수 있습니다.

다음 스크립트는 루프에서 전체 식을 구성합니다. 죄송합니다. grep -P-f 옵션을 허용하지 않으므로 패턴을 유지하기위한 큰 thumpin 변수를 만듭니다. 그렇다면 우리는 ^(.)(?:.|(.)(?:.|(.)....\3)?\2?\1$ 양식의 단일 패턴으로 단순화 할 수 있습니다. 다만 . 대신 [a-z]을 사용하면 소문자로만 제한됩니다.

head='' 
tail='' 
for i in $(seq 1 22); do 
    head="$head([a-z])(?:[a-z]|" 
    tail="\\$i${tail:+)?}$tail" 
done 
grep -P "^${head%|})?$tail$" /usr/share/dict/words 

단일 grep이 훨씬 빨리 개별적 큰 입력 파일 grep 22 또는 43 배 이상을 호출해야한다. 길이에 따라 정렬하려면 파이프 라인 끝에 필터로 추가하십시오. 사전 전체에 걸쳐 여러 번 전달하는 것보다 여전히 빠를 것입니다.

${tail+:)?}tail이 비어 있지 않은 경우에만 닫는 괄호와 물음표로 평가되며 이는 \1 역 참조를 선택 사항이 아니게하는 편리한 방법입니다. 비슷하게 ${head%|}은 최종 변경 연산자를 $head의 최종 값으로 조정합니다.

+0

그래,이게 분명 도움이 될 것 같아. prof는 어쨌든 2 개 이상의 grep 문을 필요로하지 않습니다. 다시 말하지만, 나는 완전히 완전히 bash를 처음 접했고 프로그래밍 경험이 제한적이었다. 나는 이것을 무너 뜨리고 몇 가지를 바꾸면 효과가있을 것이라고 생각합니다. 감사. – Greg

+0

'.' 대신'[a-z]'를 사용하여 소문자 단어 만보기 위해 업데이트되었습니다. 대소 문자를 구분하지 않으려면'-i' 옵션을'grep'에 추가하십시오. 리터럴 하이픈을 포함 시키려면 범위를'[-a-z]'로 확장 할 수 있습니다. – tripleee

+0

대신 'grep -P'를 사용하여'\ 9'를 넘는 역 참조를 수용하도록 업데이트되었습니다. – tripleee

2

grep을 사용해야합니까?배쉬 행복하게 당신을 위해 작업을 수행합니다

#!/bin/bash 

is_pal() { 
    local w=$1 
    while ((${#w} > 1)); do 
     [[ ${w:0:1} = ${w: -1} ]] || return 1 
     w=${w:1:-1} 
    done 
} 

while read word; do 
    is_pal "$word" && echo "$word" 
done 

저장이 banana, chmod +x banana 및 즐길 :

grep ... /usr/share/dict/words | ./banana 
:

./banana < /usr/share/dict/words 

만 적어도 세 문자로 단어를 유지하려면

소문자 만 포함하고 3 자 이상인 단어를 유지하려면

grep '^[[:lower:]]\{3,\}$' /usr/share/dict/words | ./banana 
0

재귀와 펄 호환 정규 표현식 (PCRE)를 사용하는 또 다른 방법, 무겁게 this answer에 의해 영감 : 시작을위한

grep -P '^(?:([a-z])(?=[a-z]*(\1(?(2)\2))$))++[a-z]?\2?$' /usr/share/dict/words