回答:
なぜ誰も明白な答えを与えていないのですか?
sed 's/.*\(...\)/\1/'
…またはやや目立たない
grep -o '...$'
確かに、2番目のものには、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 文字を要求します。それはこの答えがあなたに与えるものではありません:最後の3 バイトを出力します!
各文字が1バイトである限り、tail -c
機能します。したがって、文字セットがASCII
、ISO 8859-1
またはバリアントの場合に使用できます。
一般的なUTF-8
形式のようにUnicode入力がある場合、結果は間違っています。
$ printf 123αβγ | tail -c 3
�γ
この例でUTF-8
は、ギリシャ文字のアルファ、ベータ、ガンマの長さは2バイトです。
$ printf 123αβγ | wc -c
9
このオプション-m
は、少なくとも実際のUnicode文字をカウントできます。
printf 123αβγ | wc -m
6
さて、最後の6バイトで最後の3文字が得られます:
$ printf 123αβγ | tail -c 6
αβγ
そのため、tail
一般的な文字の処理をサポートせず、試してさえいません(以下を参照)。可変サイズの行を処理しますが、可変サイズの文字は処理しません。
このようにしましょう:tail
解決する問題の構造にはちょうどいいですが、データの種類には間違っています。
さらに見ると、それはあなたのGNU coreutilsの、基本的なツールのコレクションが好きなことが判明しsed
、ls
、tail
とcut
、まだ完全に国際化されていません。これは主にUnicodeのサポートに関するものです。
たとえば、cut
ここではキャラクターのサポートにテールの代わりに使用するのに適した候補です。バイトまたは文字、-c
(--bytes
)および-m
(--chars
)を操作するオプションがあります。
バージョン-m
/ 2013では、
実装されていないの--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.
参照してください、この答えに缶は、UTF-8で`カット-c`を(` --characters`)を使用していませんか?。
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
「最後の文字から3番目から3番目の文字を含む」を要求するため、長さを指定することは多少意味がありません。 、包括的」。
を使用してawk
:
awk '{ print substr( $0, length($0) - 2, length($0) ) }' file
ted
654
789
文字列が変数内にある場合、次を実行できます。
printf %s\\n "${var#"${var%???}"}"
$var
like の値から最後の3文字を削除します。
${var%???}
...そして、$var
すべての頭から取り除かれますが、次のように取り除かれました:
${var#"${var%???}"}
この方法には長所と短所があります。明るい面では、完全にPOSIXに移植可能であり、最新のシェルで動作するはずです。また、もし$var
少なくとも3文字の含まれていません、何もしますが、末尾\n
ewlineが印刷されます。あなたがあればその後、再び、欲しいそれが、その場合には印刷され、次のような追加の手順が必要になります。
last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"
その方法で$last3
は、$var
3バイト以下のバイトが含まれている場合にのみ空になります。そして、$var
しか置換される$last3
場合は$last3
空であるかunset
-と我々はそれがない知っているunset
私達はちょうどそれを設定しているため。
printf
フォーマット文字列を引用しない理由は何ですか?
${VARNAME:(-3)}
(仮定してbash
)使用しないのですか?
bash
POSIX互換性を要求する他のシェルと同様に機能します。
csh
ありません。POSIXシェル仕様はの後にモデル化されており、これは従来のBourneスタイルのシェルと両方の組み合わせをモデル化したものです。の優れたジョブ制御機能と古いボーンスタイルのI / Oリダイレクトの両方が組み込まれました。また、上記で説明した文字列操作の概念など、いくつかのことも追加しました。私の知る限り、これは従来のどの方法でも機能しない可能性があります。ksh
csh
ksh
csh
csh
あなたはこれを行うことができますが、これは少し...過剰です:
for s in unlimited 987654 123456789; do
rev <<< $s | cut -c 1-3 | rev
done
ted
654
789
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のエンコード、Python 2.7のコーデックでデコード/エンコードできます
例:
utf-16le文字列から最後の3文字を抽出し、これらの文字を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"
)
echo
あなたの防弾ソースはありますか?
decode/encode
は私の防弾ソースです。私の答えを整理しました。
LC_ALL=C
は、非常に「ダム」の設定なので、しかし、あなたはSHIFT-5にUTF-8文字列、またはKOI8などにSHIFT-5弦渡ししようとすると、それが壊れる可能性
perl -CAO -e 'print substr($ARGV[0], -3)'
がうまくいくと思います。A
@ARGV要素はUTF-8でエンコードされた文字列であることが期待され、O
STDOUTはUTF-8になります。
utf8_str
tail -n 1 revisions.log | awk '{print substr($ 0、0、length($ 0)-(length($ 0)-13))}'
最初から13文字を印刷する場合
stringにスペースが含まれている場合、printfは機能しません。
スペースを含む文字列のコードの下
str="Welcome to Linux"
echo -n $str | tail -c 3
ヌクス
printf
いかない場合は、何か非常に悪いことをしています。
printf $str
(printf "$str"
またはではなくprintf '%s' "$str"
)試みました。そして、はい、printf $str
である非常に間違っています。(echo -n $str
それほど良くはありません。)
grep -o '.\{3\}$'