テキストファイルの各行の文字数を印刷する方法


83

UNIXコマンドを使用して、テキストファイルの各行の文字数を出力したいと思います。私はそれがPowerShellで簡単であることを知っています

gc abc.txt | % {$_.length}

しかし、UNIXコマンドが必要です。

回答:


155

Awkを使用します。

awk '{ print length }' abc.txt

2
これは、各行にwc-cを適用するよりも数桁高速です。
aerijman

このタイプの問題の@aerijmanは、通常、プロセスの作成数が最もパフォーマンスの違いを生むものです。
MarcH 2018

ファイルの行に絵文字が含まれている場合、これは期待される長さを生成しません。
user55075 3519

@ user5507535、実際に期待する「長さ」によって異なります。Unicodeには多くの可能な定義があります(mawkはバイトを使用し、gawkをチェックしませんでした)。
JanHudec19年

16
while IFS= read -r line; do echo ${#line}; done < abc.txt

これはPOSIXなので、どこでも機能するはずです。

編集:ウィリアムによって提案されたように-rを追加しました。

編集:Unicodeの処理に注意してください。ロケールが正しく設定されているBashとzshはコードポイントの数を表示しますが、dashはバイトを表示するため、シェルの機能を確認する必要があります。そして、とにかくUnicodeには他にも多くの可能な長さの定義があるので、実際に何が必要かによって異なります。

編集:IFS=先頭と末尾のスペースが失われないように接頭辞を付けます。


+1、ただし...入力に「\」が含まれている場合、これは失敗します。read -rを使用
William Pursell 2012年

ファイルの行に絵文字が含まれている場合、これは期待される長さを生成しません。
user55075 3519

@ user5507535、実際には、予想される「長さ」によって異なります。Unicodeには多くの可能な定義があります(ただし、この場合、シェルが異なれば実際には異なることを行います)。
JanHudec19年

任意のデータを読み込みたいときIFS=は、必ずreadコマンドに設定してください。だからIFS= read -rreadを使用IFSして単語分割を行い、分割されたすべての単語が1つの使用可能な変数(line)に貼り付けられたとしても、元のすべての区切り文字または1つの潜在的に異なる文字と一緒に貼り付けられる保証はありません。もの。たとえば、デフォルトのIFSを使用すると、行foo barがになりfoo bar、7つのスペースが失われる可能性があります。(Stack Overflowがこのコメントの文字列の例で隣接するスペースを失ったように)。
mtraceur

@mtraceurのドキュメントには、「残りの単語とその間にある区切り文字は姓に割り当てられる」と明示的に記載されているため、元の区切り文字と一緒に貼り付けられます。ただし、これでは、実際に失われる先頭末尾の区切り文字は処理されません。ですから、あなたは正しいのですが、IFS設定する必要がありますが、そうでない場合の問題はもっと微妙です。
JanHudec19年

4

上記の他の回答を試しましたが、大きなファイルを処理する場合、特に1行のサイズが使用可能なRAMの約1/4を超えると、適切な解決策にはほど遠いものになります。

この問題では必要ありませんが、bashとawkの両方が行全体を丸呑みします。十分なメモリがある場合でも、行が長すぎるとBashはエラーになります。

私は非常に単純で、かなり最適化されていないpythonスクリプトを実装しました。これは、大きなファイル(1行あたり最大4 GB)でテストした場合、丸呑みせず、与えられたものよりもはるかに優れたソリューションです。

これが本番環境でタイムクリティカルなコードである場合は、これが実際にボトルネックであることをテストした後、Cでアイデアを書き直すか、読み取り呼び出しでより適切な最適化を実行できます(一度に1バイトだけを読み取るのではありません)。

コードでは、改行が改行文字であると想定しています。これはUnixにとっては適切な想定ですが、Mac OS / WindowsではYMMVです。最後の行の文字数が見落とされないように、ファイルが改行で終わっていることを確認してください。

from sys import stdin, exit

counter = 0
while True:
    byte = stdin.buffer.read(1)
    counter += 1
    if not byte:
        exit()
    if byte == b'\x0a':
        print(counter-1)
        counter = 0

1
質問は「テキスト」ファイルに関するものでした。1行あたり4GBは、テキストファイルの合理的な定義には当てはまらないと思います。
MarcH 2018年

3

以下を使用した例を示しxargsます。

$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file

この「echo%」は、シェルからの引用が必要な安全でない文字を処理しません。さらに、「xargs」は、元の投稿者が要求した改行だけでなく、スペースと改行でファイルを分割します。
ウシ

1

これを試して:

while read line    
do    
    echo -e |wc -m      
done <abc.txt    

意味echo -e | wc -mしましたね。コマンドの無駄な使用です。シェルは変数内の文字を数えることができます。Plusecho -eは完全に互換性がなく、シェルの半分で機能しますが、いくつかのエスケープシーケンスで開始すると、他のいくつかでは機能し、残りは何も機能しません。
Jan Hudec 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.