명령 출력에서 문자 수를 계산해야 하는 스크립트를 작성 중입니다.단계.
예를 들어, 이 명령의 출력 길이가 10자이므로 이 명령을 사용하면 readlink -f /etc/fstab
결과가 반환되어야 합니다 .10
이는 다음 코드를 사용하여 변수를 저장함으로써 달성할 수 있습니다.
variable="somestring";
echo ${#variable};
# 10
불행하게도 명령으로 생성된 문자열에 동일한 수식을 사용하면 작동하지 않습니다.
${#(readlink -f /etc/fstab)};
# bash: ${#(readlink -f /etc/fstab)}: bad substitution
먼저 출력을 변수에 저장하면 이 작업을 수행할 수 있다는 것을 알고 있습니다.
variable=$(readlink -f /etc/fstab);
echo ${#variable};
하지만 추가 단계를 제거하고 싶습니다.
가능합니까? Almquist 셸(sh)과 호환되는 내장 유틸리티나 표준 유틸리티를 사용하는 것이 가장 좋습니다.
답변1
그리고GNU 표현:
$ expr length + "$(readlink -f /etc/fstab)"
10
GNU에는 다음 인수가 , ...와 같은 연산자 인 경우에도 문자열로 처리되도록 하는 +
특수 기능이 있습니다 .expr
expr
match
length
+
위의 코드는 출력에서 모든 후행 개행 문자를 제거합니다. 이 문제를 해결하려면:
$ expr length + "$(readlink -f /etc/fstab; printf .)" - 2
10
결과가 차감됩니다.2끝에 개행 문자와 추가한 문자가 있기 때문입니다 readlink
..
유니코드 문자열의 경우 expr
문자 수 대신 문자열 길이를 바이트 단위로 반환하므로 작동하지 않는 것 같습니다(참조654호선)
$ LC_ALL=C.UTF-8 expr length ăaa
4
따라서 다음을 사용할 수 있습니다.
$ printf "ăaa" | LC_ALL=C.UTF-8 wc -m
3
앞쪽:
$ expr " $(readlink -f /etc/fstab; printf .)" : ".*" - 3
10
명령 대체 앞의 공백은 명령이 그것으로 시작하는 문자열에서 충돌하는 것을 방지하므로 -
3을 빼야 합니다.
답변2
쉘 내장 기능을 사용하여 이 작업을 수행하는 방법을 잘 모르겠습니다(비록 Gnouc은) 그러나 표준 도구가 도움이 될 수 있습니다.
wc -m
이를 사용하여 문자 수를 계산할 수 있습니다 . 불행하게도 마지막 개행 문자도 계산되므로 먼저 이를 제거해야 합니다.readlink -f /etc/fstab | tr -d '\n' | wc -m
물론 당신은 사용할 수 있습니다
awk
readlink -f /etc/fstab | awk '{print length($0)}'
아니면 펄
readlink -f /etc/fstab | perl -lne 'print length'
답변3
나는 보통 이렇게 합니다:
$ echo -n "$variable" | wc -m
10
명령을 실행하려면 다음과 같이 조정합니다.
$ echo -n "$(readlink -f /etc/fstab)" | wc -m
10
이 방법은 두 단계를 하나의 라이너로 결합한다는 점을 제외하면 2단계에서 수행한 것과 유사합니다.
답변4
이는 작동 dash
하지만 대상 변수가 완전히 비어 있거나 설정되지 않아야 합니다. 그렇기 때문에 실제로는둘명령 - $l
첫 번째 명령에서 명시적으로 지웠습니다.
l=;printf '%.slen is %d and result is %s\n' \
"${l:=$(readlink -f /etc/fstab)}" "${#l}" "$l"
산출
len is 10 and result is /etc/fstab
그게 전부 쉘 내장 기능입니다(물론 제외 readlink
). 하지만 현재 쉘에서 이를 평가한다는 것은 len을 얻기 전에 할당해야 함을 의미합니다. 이것이 바로 %.s
형식 문자열의 첫 번째 인수를 무시 하고 목록 끝에 arg 리터럴 값을 printf
추가한 이유입니다. printf
.
그리고 eval
:
l=$(readlink -f /etc/fstab) eval 'l=${#l}:$l'
printf %s\\n "$l"
산출
10:/etc/fstab
동일한 결과에 가까워질 수 있지만 첫 번째 명령의 변수 출력 대신 표준 출력으로 표시됩니다.
PS4='${#0}:$0' dash -cx '2>&1' "$(readlink -f /etc/fstab)"
...어디에 써있는지...
10:/etc/fstab
...현재 쉘의 변수에 값을 할당하지 않고 파일 설명자 1에.