Unixでは、sedのような単純なコマンドを使用して、ファイルの最後の文字を印刷する方法はありますか?
テールは適切なツールであり、sedではありません。
tail -c 1 filename
tail -c 2 file
それを行う必要があります。理論的には-c1であるはずですが、実践によって私は間違っていることがわかりました。
編集:ファイルに無視したい行末文字がある場合は2.1です。それ以外の場合は2.1です。
これを試して cat filename | tail -c -1
最後の行が空でない限り、これは機能するはずです。
sed -n '$s/.*\(.\)$/\1/p' file
使用:cat test | sed -e "s/^.*\(.\)$/\1/"
ここで、testはファイルの名前です。
読者の利益のために:
ここにはいくつかの誤解があります。 tail -c1 file
は確かにファイルの最後の文字を出力する正しいコマンドですが、これは、ファイルがNL
で終了するかどうかを検出するために簡単に使用することはできません。シェルレベル、POSIXシェルがコマンド出力を処理する方法による:
if last_character="$(tail -c1 "$file")"; then ..
# WRONG! last_character will be empty on NL, as well as on an empty file
いくつかの不明な理由のために、POSIXは、すべての後続のNLが削除されると定義しています。世の中にあるほとんどすべてのシェルスクリプトは、次のような最も単純なものでさえ、この罠に陥る
cd "$(dirname -- "$0")" || exit # Wrong, see: mkdir $'\n'
base="$(basename -- "$0" .sh)" || exit # Wrong, see: mv script.sh $'\n.sh'
攻撃者は、ソフトリンクを使用してこのPOSIX標準を悪用する可能性さえあります。
ここでは
bash
バージョン4構文を使用していることに注意してください。
次のようなことができます:
set -o pipefail
if tail -c1 file | { IFS= read -rd '' var; postprocess "$var"; }; then ..
しかし、これはサブシェルのためにPITAです。または
6< <(tail -c1 file) IFS= read -ru6 -d '' var
これも同様に奇妙です。 (ここでtail
の失敗を適切に検出する方法など)
しかし、以下のレシピは通常は機能します:
var="$(tail -c1 file && echo x)" && var="${var%x}" || error ..
常に余分なNLを追加するコマンド(basename
やdirname
など、ほぼすべてのコマンドがこれを実行します)の場合、これを次のように調整する必要があります。
var="$(basename -- "$file" && echo x)" && var="${var%$'\nx'}" || error ..
#----------------------------------------------------^^^^^^ change
このレシピは他の通常の状況でも機能することに注意してください。
# This is only correct here because we only expect a single filename
echo wrong > $'file'
echo right > $'file\n'
wrongname="$(fgrep -lx right file*)" || notfound
correctname="$(fgrep -lx right file* && echo x)" && correctname="${correctname%$'\nx'}" || notfound
wrongname
にはfile
が含まれ、correctname
にはfile\n
が含まれます(\n
はNL
を表します)。両方のファイルが存在し、データが含まれているため、間違った内容のファイルでwrongname
バリアントを使用したというエラーはすぐには発見できません。
はい、少々気の利いたものですが、それでも必要な場合があります。