답변:
아무도 분명한 대답을하지 않은 이유는 무엇입니까?
sed 's/.*\(...\)/\1/'
… 또는 약간 덜 명백한
grep -o '...$'
물론 두 번째 문자는 3 자 미만의 줄이 사라지는 단점이 있습니다. 그러나 질문은이 사건의 행동을 명시 적으로 정의하지 않았습니다.
echo "unlimited" | python -c "print raw_input()[-3:]"
"echo unlimited" | java -jar EnterpriseWordTrimmer.jar이지만 문자 조작을 위해 더 무거운 언어를 가져올 필요는 없다고 생각합니다.
java -server -Xms300M -Xmx3G -XX:+UseParallelGC -cp /path/to/all/the/jars/ -Dinput.interactive=false -Dinput.pipe=true -Dconfig.file=/path/to/config/last-three-letters.cfg -jar ...
grep -o -P '.{0,3}$'줄이 3 자 미만인 경우에도 마지막 3자를 인쇄합니다. -P버팀대를 피할 필요가 없습니다.
문자 수를 계산하기 위해 정규식이나 두 개 이상의 프로세스가 필요하지 않습니다. 파일 의 마지막 줄 을 표시하는 데 자주 사용되는
명령 에는 옵션 ( )이 있으며 이는 올바른 도구 인 것 같습니다.tail-c--bytes
$ printf 123456789 | tail -c 3
789
(쉘에있을 때 mikeserv의 대답과 같은 방법을 사용하는 것이 좋습니다 tail. 프로세스 시작을 저장하지 않기 때문입니다 .)
이제 마지막 세 문자 를 요구 합니다 . 이 답변이 제공하는 것은 아닙니다. 마지막 3 바이트를 출력합니다 !
각 문자가 1 바이트 인 tail -c한 작동합니다. 이 사용할 수 있도록 문자 집합 인 경우 ASCII, ISO 8859-1또는 변형.
공통 UTF-8형식 과 같이 유니 코드 입력이있는 경우 결과가 잘못되었습니다.
$ printf 123αβγ | tail -c 3
�γ
이 예 UTF-8에서 그리스 문자 인 alpha, beta 및 gamma는 2 바이트 길이입니다.
$ printf 123αβγ | wc -c
9
이 옵션 -m은 최소한 실제 유니 코드 문자를 계산할 수 있습니다.
printf 123αβγ | wc -m
6
마지막 6 바이트는 우리에게 마지막 3 문자를 줄 것입니다 :
$ printf 123αβγ | tail -c 6
αβγ
따라서 tail일반 문자 처리를 지원하지 않으며 시도조차하지 않습니다 (아래 참조) : 가변 크기 줄은 처리하지만 가변 크기 문자는 처리하지 않습니다.
이런 식으로하자 : tail문제의 구조가 해결하기에는 옳지 만 데이터 종류에는 틀리다.
더 찾고, 그것은 그대 GNU의로 coreutils, 기본 도구 모음이 좋아하는 것으로 나타났다 sed, ls, tail과 cut, 아직 완전히 국제화되지 않습니다. 주로 유니 코드 지원에 관한 것입니다.
예를 들어, cut문자 지원을 위해 꼬리 대신 여기를 사용하는 것이 좋습니다. 바이트 또는 문자에 대한 작업 옵션이 있습니다 -c( --bytes) 및 -m(--chars ).
2013 년 버전 기준 으로 그 -m/ 만
구현되지 않았습니다!--chars
cut (GNU coreutils) 8.21
보낸 사람 info cut:
`-c CHARACTER-LIST'
`--characters=CHARACTER-LIST'
Select for printing only the characters in positions listed in CHARACTER-LIST.
The same as `-b' for now, but internationalization will change that.
cut기반 솔루션 만 보이지 않습니다.
tail는 문자가 아닌 바이트를 처리하도록 명시 적으로 지정합니다 . 한 번은 문자를 선택할 수있는 새로운 옵션을 추가하기위한 패치를 만들었지 만 병합 된 적이 없다고 생각합니다 :-/
tail -c3 -n10 /var/log/syslog
tail -c3 -n10 /var/log/syslog은 마지막 10 줄을 요구하며, 그것은 저에게 효과적입니다. 옵션을 사용하고 -c3그 후에 충돌하는 옵션을 사용 -n10합니다. 나중 옵션이 우선합니다.
텍스트가이라는 쉘 변수 STRING에있는 경우 bash, zsh또는 mksh쉘 에서이를 수행 할 수 있습니다 .
printf '%s\n' "${STRING:(-3)}"
또는
printf '%s\n' "${STRING: -3}"
또한 구문이 시작되는 ksh93과 함께 작동하는 이점이 있습니다.
요점은 :에서와 분리되어야 -하며 그렇지 않으면 ${var:-default}Bourne 쉘 의 연산자 가됩니다 .
zsh또는 yash쉘 에서 동등한 구문은 다음과 같습니다 .
printf '%s\n' "${STRING[-3,-1]}"
${STRING:(-3):3}합니다 (지정 길이 , 필드) ${STRING: -3}(사이 공백 :과를 -) 또는 ${STRING: -3:3}.
3것은 "마지막 문자에서 세 번째 문자의 세 문자를 포함하여"를 요구하기 때문에 다소 무섭습니다. "마지막 문자에서 세 번째 문자부터 세 번째 문자까지"와 같은 실제 작업에서 동일한 작업이됩니다 , 포함한".
문자열이 변수에 있으면 다음을 수행 할 수 있습니다.
printf %s\\n "${var#"${var%???}"}"
그러면 $varlike 의 값에서 마지막 세 문자가 제거됩니다 .
${var%???}
... 그리고 나서 $var모든 것의 머리에서 벗겨 지지만 막 벗겨진 것 :
${var#"${var%???}"}
이 방법에는 단점과 단점이 있습니다. 밝은면에서는 POSIX로 완벽하게 이동할 수 있으며 모든 현대 쉘에서 작동해야합니다. 또한, 만약 $var3 자 이상을 포함하지 않습니다 아무것도 하지만 후행 \newline가 인쇄됩니다. 당신이 경우 다시, 원하는 이 경우 인쇄, 당신은 같은 추가 단계가 필요하다
last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"
그런 식으로 3 바이트 이하의 바이트를 포함하는 $last3경우에만 비어 $var있습니다. 그리고 비어 있거나 비어있는 경우 $var로만 대체 되며 우리는 그것을 설정했기 때문에 그렇지 않습니다 .$last3$last3unsetunset
printf형식 문자열을 인용하지 않는 이유는 무엇입니까?
${VARNAME:(-3)}(가정 bash)을 사용하지 않습니까?
bashPOSIX 호환성을 주장하는 다른 쉘 에서도 잘 작동합니다 .
csh가 아닙니다 . POSIX 쉘 사양은 이후 에 모델링되었으며 , 전통적인 Bourne 스타일 쉘과 자체 조합을 통해 모델링되었습니다 . 모두 통합 의 우수한 작업 제어 기능과 기존의 Bourne의-스타일 'I / O 리디렉션을. 또한 위에서 설명한 문자열 조작 개념과 같은 것들도 추가했습니다. 이것은 내가 아는 한 전통적인 방식 으로는 작동하지 않을 것 입니다. 미안합니다. kshcshkshcshcsh
utf-8 문자열에 대한 방탄 솔루션 :
utf8_str=$'\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82' # привет
last_three_chars=$(perl -CAO -e 'print substr($ARGV[0], -3)' "$utf8_str")
또는 사용하십시오 :
last_three_chars=$(perl -MEncode -CO -e '
print substr(decode("UTF-8", $ARGV[0], Encode::FB_CROAK), -3)
' "$utf8_str")
잘못된 데이터 처리를 방지합니다.
예:
perl -MEncode -CO -e '
print substr(decode("UTF-8", $ARGV[0], Encode::FB_CROAK), -3)
' $'\xd0\xd2\xc9\xd7\xc5\xd4' # koi8-r привет
다음과 같이 출력합니다 :
utf8 "\xD0" does not map to Unicode at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 175.
로케일 설정에 의존하지 않습니다 (예 :로 작동 LC_ALL=C). Bash, sed, grep, awk, rev이 같은 필요합니다LC_ALL=en_US.UTF-8
일반적인 해결책 :
uchardet으로 인코딩을 감지 할 수 있습니다 . 관련 프로젝트 도 참조하십시오 .
Perl의 Encode , Python 2.7의 코덱 으로 디코딩 / 인코딩 할 수 있습니다
예 :
utf-16le 문자열에서 마지막 세 문자를 추출하고이 문자를 utf-8로 변환
utf16_le_str=$'\xff\xfe\x3f\x04\x40\x04\x38\x04\x32\x04\x35\x04\x42\x04' # привет
chardet <<<"$utf16_le_str" # outputs <stdin>: UTF-16LE with confidence 1.0
last_three_utf8_chars=$(perl -MEncode -e '
my $chars = decode("utf-16le", $ARGV[0]);
my $last_three_chars = substr($chars, -3);
my $bytes = encode("utf-8", $last_three_chars);
print $bytes;
' "$utf16_le_str"
)
참조 : perlunitut , 파이썬이 유니 코드 HOWTO
echo방탄 출처는 무엇입니까?
decode/encode는 내 방탄 소스입니다. 내 대답을 정리했습니다.
LC_ALL=C매우 "멍청한"설정이기 때문에 "작동" 하지만 UTF-8 문자열을 SHIFT-5로 전달하거나 SHIFT-5 문자열을 KOI8 등으로 전달하려고하면 중단 될 수 있습니다.
perl -CAO -e 'print substr($ARGV[0], -3)'잘 작동 한다고 생각 합니다. A@ARGV 요소는 UTF-8로 인코딩 된 문자열 O이어야하고 STDOUT은 UTF-8입니다.
utf8_str
tail -n 1 개정 .log | awk '{print substr ($ 0, 0, length ($ 0)-(길이 ($ 0) -13))}'
처음부터 처음 13자를 인쇄하려면
문자열에 공백이 있으면 printf가 작동하지 않습니다.
공백이있는 문자열의 코드 아래
str="Welcome to Linux"
echo -n $str | tail -c 3
Nux
printf하지 않으면, 당신은 매우 잘못 하고있는 것입니다.
printf $str( printf "$str"또는 대신 printf '%s' "$str") 시도했습니다 . 그리고, 예, printf $str있습니다 매우 잘못. ( echo -n $str더 좋은 것은 아닙니다).
grep -o '.\{3\}$'