catコマンドから最初のX文字を取得しますか?


42

シェルスクリプトの変数に出力するテキストファイルがあります。ただし、最初の50文字のみが必要です。

使用してみましたcat ${filename} cut -c1-50が、最初の50文字をはるかに超えていますか?これはcut行を探しているためかもしれません(100%確実ではありません)が、このテキストファイルは1つの長い文字列である可能性があります。

catコマンドから最初のX文字を取得するためにパイプできるユーティリティはありますか?


10
忘れた|cat ${filename} | cut -c1-50
DisplayName

@DisplayNameが修正されました。再入力エラーをキャッチしてくれてありがとう。
jkj2000 14年

1
@ jkj2000、それが元の質問だったので、私は古いバージョンに戻りました。
ラメシュ

回答:


61
head -c 50 file

これは、最初の50バイトを返します。

コマンドがすべてのOSで常に同じように実装されるわけではないことに注意してください。LinuxおよびmacOSでは、このように動作します。Solaris(11)では、/ usr / gnu / bin /にあるgnuバージョンを使用する必要があります


headに-cオプションがありません。代わりにdd(1)に行きます。
ミラビロス

7
OPがバイトではなく最初のX文字を要求したため、この回答はファイルにASCII文字のみが含まれていることを前提としていることに注意してください。
カリモ

2
@mirabilosポータブルではないかもしれませんが、私のバージョン(GNU coreutils 5.97)はサポートしています。
ヨッサリアン

1
-cただし、POSIXは有効なオプションとして定義されていないため、ローカル環境に完全に依存しています。unix.com/man-page/posix/1/head
Jules

1
@Calimoはい、知っていますが、100文字のテキストファイルを作成し、コマンドを実行して50文字を印刷しようとしました。しかし、あなたはASCIIについては正しいのですが、OPがこれに答えたとしてフラグを立てたので、彼の場合には何もありませんでした。
DisplayName

27

あなたのcutあなたがそれにデータを渡すためにパイプを使用する場合、コマンドは動作します:

cat ${file} | cut -c1-50 

または、猫の無駄な使用を避けて、少し安全にします:

cut -c1-50 < "$file"

上記のコマンドは、各入力行の最初の50文字(またはcut実装によってはバイト)を出力することに注意してください。あなたが言うように、あなたのファイルが1つの巨大な行であるならば、それはあなたが期待することをするべきです。


8
dd status=none bs=1 count=50 if=${filename}

これは、最初の50バイトを返します。


ddにstatus=noneフラグがありません。2>/dev/null代わりに使用してください(適切に引用してください):(dd if="$filename" bs=1 count=50 2>/dev/nullそれでも、使用bs=50 count=1するsyscallの数を減らすために使用することを検討してください)。
ミラビロス

1
@mirabilos ddはstatus=none、Ubuntu 14.04、coreutils 8.21を使用している場合には使用できますが2>/dev/null、以前のバージョンを使用している場合は使用する権利があります。
doneal24

1
@mirabilosほとんどのLinuxディストリビューションは、FreeBSDや他のBSDと同様にGNU coreutilsを使用しています。Solarisでは、パッケージgnu-coreutilsとして入手できます。はい、これは「Unix&Linux」であり、UnixおよびLinuxシステムは両方ともGNU coreutilsを使用します。
doneal24

2
いいえ、Unixシステムは一般的にGNUユーティリティを使用しません。GNUは、「GNUはUnixではありません」の頭字語です。ポータブルソリューションに固執するか、GNUのみのソリューションを提供する必要がある場合はその旨を明記し、可能な場合は同等のポータブルソリューションを提示してください。
ミラビロス

1
厳密に言えば、それはread()50バイトのいずれかを行います。場合はfile、インスタンスと少ない文字のためのパイプが一度に利用可能である場合、少ないバイト数が返されます。と同等のものhead -c50を使用するには、GNU固有のを使用する必要がありますiflag=fullblock
ステファンシャゼル14年

4

これまでのほとんどの回答では、1バイト= 1文字であると想定していますが、非ASCIIロケールを使用している場合はそうではありません。

それを行うためのもう少し堅牢な方法:

testString=$(head -c 200 < "${filename}") &&
  printf '%s\n' "${testString:0:50}"

これが仮定することに注意してください:

  1. あなたは使用しているksh93bash(または最近のzshmksh(でサポートされているのみで、マルチバイト文字セットにはかかわらず、mkshUTF-8であり、唯一の後set -o utf8-mode))とのバージョンheadことを裏付けている-c(ほとんどが、今日やるが、厳密には標準ではありません)。
  2. 現在のロケールは、ファイルと同じエンコーディングに設定されます(タイプlocale charmapおよびそれfile -- "$filename"を確認するため)。そうでない場合は、ieで設定します。LC_ALL=en_US.UTF-8
  3. headすべての文字が最大4バイトでエンコードされる最悪のUTF-8を想定して、ファイルの最初の200バイトを取得しました。これは私が考えることができるほとんどの場合をカバーするはずです。

もちろん、これはGNU head、またはnōn-standard -cオプションを追加する別の実装も想定しています。しかし、すでにGNU bashが必要です。(注:mkshUTF-8エンコードファイルの場合、UTF-8モードでこれを行うことができます。)OPにオクテットまたはマルチバイト文字が必要かどうかを尋ねます。「文字」は漠然とした/古い用語です。
ミラビロス

また、空白の改行またはワイルドカードが含まれている$filename$testString、含まれていないか、またはで始まることを前提としています-
ステファンシャゼル14年

${var:offset:length}あなたがここに使用している構造が、実際に来てからksh93も、最近のバージョンでサポートされていますzshzshそれ自身を持っています$testString[1,50])。あなたは必要${testString:0:50}ksh93し、zshしかし。
ステファンシャゼル14年

上記のコメントに対処するために私の答えを編集した
ばかり

2
grep -om1 "^.\{50\}" ${filename}

その他のバリアント(ファイルの最初の行用)

(IFS= read -r line <${filename}; echo ${line:0:50})

これは高レベルのツールの不正使用であり、ロケールに対応している場合など、必要な処理を行わない傾向があります。
ミラビロス

@mirabilosあなたは何を意味しています下のハイレベルのツールreadecho?またはbash expansion
コスタス

grep(regexp)、そして、はい、ここでのシェルの使用(ヒント:最初の行は大きいかもしれません)。(言われているように、bashismはPOSIXにもありませんが、ほとんどのシェルはそれを実装しています。)
ミラビロス

0

1. ASCIIファイルの場合、@ DisplayNameのように実行します。

head -c 50 file.txt

たとえば、file.txtの最初の50文字を出力します。

2.バイナリデータの場合、hexdump16進文字として出力するために使用します。

hexdump -n 50 -v file.bin

たとえば、file.binの最初の50バイトを出力します。

-v詳細オプションを指定しないと、hexdump繰り返される行が*代わりにアスタリスク()に置き換えられることに注意してください。ここを参照してください:https://superuser.com/questions/494245/what-does-an-asterisk-mean-in-hexdump-output/494613#494613を


-2

このためにsedを使用すると、問題に非常に簡単に取り組むことができます

sed -e 's/^\(.\{50\}\).*/\1/' yourfile

「私は最初の50文字を必要とし」これはUUOC(猫の無駄な使用)することなく、要求されたものを実現:これは、それはOPの質問を解決するかどうかdownvoted得た方法を知って好奇心が強い
munkeyoto

1
この答えは、ファイルの最初の50文字だけでなく、ファイルの各行の最初の50文字を示します。また、すべての行の長さが50文字未満の場合、何も印刷しません。ソリューションは、次のようにうまく機能しますsed -n -e '1s/^\(.\{50\}\).*/\1/p' ${filename}
doneal24

理解できるのは、head -n 1 | sed -e 's / ^(。\ {50 \})。* / \ 1 /' ...そして、問題は解決したでしょう。OPは次のように述べた。「最初の50の文字が必要」
munkeyoto

1
いや。最初の行の長さが49文字しかない場合、何も出力されません。
doneal24

ダグ私はこれを初めて理解しましたが、行に含まれる文字が50文字未満の場合、OPは印刷について何も言及していませんでしたので、あなたのポイントを見ることができませんhead:head -n 1 $ {filename} | sed -n -e '1s / ^(。\ {50 \})。* / \ 1 / p'
munkeyoto
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.