답변:
아무도 분명한 대답을하지 않은 이유는 무엇입니까?
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%???}"}"
그러면 $var
like 의 값에서 마지막 세 문자가 제거됩니다 .
${var%???}
... 그리고 나서 $var
모든 것의 머리에서 벗겨 지지만 막 벗겨진 것 :
${var#"${var%???}"}
이 방법에는 단점과 단점이 있습니다. 밝은면에서는 POSIX로 완벽하게 이동할 수 있으며 모든 현대 쉘에서 작동해야합니다. 또한, 만약 $var
3 자 이상을 포함하지 않습니다 아무것도 하지만 후행 \n
ewline가 인쇄됩니다. 당신이 경우 다시, 원하는 이 경우 인쇄, 당신은 같은 추가 단계가 필요하다
last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"
그런 식으로 3 바이트 이하의 바이트를 포함하는 $last3
경우에만 비어 $var
있습니다. 그리고 비어 있거나 비어있는 경우 $var
로만 대체 되며 우리는 그것을 설정했기 때문에 그렇지 않습니다 .$last3
$last3
unset
unset
printf
형식 문자열을 인용하지 않는 이유는 무엇입니까?
${VARNAME:(-3)}
(가정 bash
)을 사용하지 않습니까?
bash
POSIX 호환성을 주장하는 다른 쉘 에서도 잘 작동합니다 .
csh
가 아닙니다 . POSIX 쉘 사양은 이후 에 모델링되었으며 , 전통적인 Bourne 스타일 쉘과 자체 조합을 통해 모델링되었습니다 . 모두 통합 의 우수한 작업 제어 기능과 기존의 Bourne의-스타일 'I / O 리디렉션을. 또한 위에서 설명한 문자열 조작 개념과 같은 것들도 추가했습니다. 이것은 내가 아는 한 전통적인 방식 으로는 작동하지 않을 것 입니다. 미안합니다. ksh
csh
ksh
csh
csh
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\}$'