파일에서 여러 단어와 문자를 찾는 소스 코드가 있습니다.
#!/bin/bash
w=0
cc=0
for i in `cat $1`
do
j=$i
echo $j
w=$(($w+1))
c=`expr $j:'.*'`
cc=$(($cc+$c))
done
echo "no of characters" $cc
echo "no of words" $w
하지만 터미널에서 실행하면 다음과 같은 오류 메시지가 표시됩니다. ^ ./countWordChar 1.c hello ./countWordChar: line 10: 0+hello:.*
: 표현식의 구문 오류(오류 플래그는 ":.*"
) 문자 수 0 단어 수 1
코드의 10행은 입니다 cc=$(($cc+$c))
. 분명히 c 변수의 값은 단어의 문자 수가 아니라 단어 자체입니다.
내 1.c 파일의 내용은 다음과 같습니다.
hello world
hello
코드에 문제가 있나요?
추신. 파일의 문자 수를 계산하는 명령이 내장되어 있다는 것을 알고 있지만 작업에 따라 이전 코드를 사용해야 합니다.
답변1
유틸리티 expr
는 인수를 표현식으로 구문 분석합니다. 연산자는 독립 인수로 표시되어야 합니다.
expr "$j" : '.*'
위에는 , 및 콘텐츠의 expr
4개 매개변수가 전달됩니다 . expr
콘텐츠가 or(또는 일부 구현에서는 유사한 것)이 아니라고 가정하면 패턴 일치 연산자가 적용되는 콘텐츠로 사용됩니다.$j
:
.*
$j
(
!
length
expr
:
$j
더욱 강력하게 만들려면 다음이 필요합니다.
expr " $j" : '.*' - 1
(공백으로 시작하는 두 번째 인수는 expr 연산자로 인식되지 않으므로 위의 문제가 해결됩니다.)
그리고
expr $j:'.*'
이는 두 개의 인수가 됩니다(그리고 expr
다음 내용(공백이나 와일드카드가 포함되지 않는다고 가정, 아래 참조)). (명령 이름 외에) 인수가 하나만 표시되므로 작업이 요청되지 않습니다. 이는 단지 에코 전용 문자열 인수일 뿐입니다.$j
:.*
$j
expr
expr
이제 코드에는 다른 많은 문제가 있습니다.
변수 확장 및 명령 대체( $((...))
또는 `...`
사용하지 않는 형식),인용되지 않은 경험이 있을 때split+glob
. split
섹션의 일부 `cat $1`
( 이어야 함 $(cat < "$1")
)를 단어로 분할하기를 원하지만 glob 부분은 원하지 않습니다. 그렇지 않으면 *
현재 디렉토리의 파일 목록으로 단어를 확장해야 합니다. 다른 모든 변수 확장은 인용되어야 합니다. 필수 항목이지만 따옴표는 문제가 되지 않습니다).
반품,echo
임의의 데이터 와 함께 사용할 수 없습니다.
따라서 다음과 같아야 합니다.
w=0 c=0
set -f # disable glob
for i in $(cat < "$1"); do
printf '%s\n' "$i"
w="$((w + 1))"
c="$(expr " $i" : '.*' + "$c" - 1)"
done
답변2
명령은 expr $j:'.*'
하나 expr
의 매개변수를 수신합니다.
명령은 expr
이것을 이해하지 못합니다.
이 명령은 expr
각 매개변수를 명확하게 구분해야 합니다.
expr "$j" ":" '.*'
이는 명령에 제공되는 세(3) 개의 매개변수입니다 expr
. "
주변 따옴표는 :
실제로 필요하지 않습니다. $j
오해를 피하기 위해 다음과 같이 문자열 앞에 공백을 사용하는 것이 좋습니다 .
expr " $j" : '.*'
이렇게 하면 스크립트가 다음과 같이 됩니다.
#!/bin/dash
w=0 cc=0
for i in `cat $1`; do
echo "$j"
w=$(($w+1))
c=`expr " $i" : '.*'`
cc=$((cc+c))
done
echo "no of characters" $cc
echo "no of words" $w
그러나 이것은 bash 스크립트라기보다는 대시 스크립트에 더 가깝습니다(이것이 질문에 태그를 지정하는 방법입니다).
단순화된 bash 스크립트는 다음과 같습니다.
#!/bin/bash
w=0 cc=0
for i in $(< $1)
do
((w++))
cc=((cc+${#i}))
done
echo "no of characters" "$cc"
echo "no of words" "$w"
동일하지만 약간 $(< $1)
더 빠릅니다 $(cat $1)
. w를 늘리려면 더 짧은 을 사용하십시오 w++
. 문자 수를 계산하려면 $i
길이를 as 로 사용할 수 있습니다 ${#i}
.
또는 더 짧게:
#!/bin/bash
w=0 cc=0
for i in $(< $1)
do (( w++ , cc += ${#i} ))
done
printf "no of characters %s\nno of words %s\n" "$cc" "$w"
bash(2.04-devel 이상)를 사용하여 쉼표 연산자 를 ,
사용하고 .cc += ${#i}
cc = cc + ${#i}