명령 출력의 문자 수를 계산하는 데 필요한 스크립트를 작성 중입니다.한 걸음.
예를 들어 해당 명령의 출력 길이가 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:
$ 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
쉘 내장 기능을 사용하여 이 작업을 수행하는 방법을 잘 모르겠습니다(그누크는 그래도) 그러나 표준 도구가 도움이 될 수 있습니다.
문자 수를 계산하는 것을 사용할 수 있습니다
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
의 첫 번째 인수를 무시 printf
하고 다시 추가하는 이유입니다. printf
의 인수 목록 끝에 있는 리터럴 값입니다 .
와 함께 eval
:
l=$(readlink -f /etc/fstab) eval 'l=${#l}:$l'
printf %s\\n "$l"
산출
10:/etc/fstab
동일한 결과에 가까워질 수 있지만 첫 번째 명령의 변수 출력 대신 stdout에서 결과를 얻습니다.
PS4='${#0}:$0' dash -cx '2>&1' "$(readlink -f /etc/fstab)"
...글을 쓰는 중...
10:/etc/fstab
...현재 쉘의 변수에 값을 할당하지 않고 파일 설명자 1에.