タブ区切りのテキストファイルをインポートし、各行を80文字に切り捨てるコマンドは何ですか?

タブ区切りのテキストファイルをインポートし、各行を80文字に切り捨てるコマンドは何ですか?

(時々)タブで区切られたデータを含む複数行のテキストファイルがあります。私はそれを参照できるようにファイルを出力したいと思います。それで、各行の最初の80文字だけを見たいです。 (私は重要な内容を各行の前に置くようにテキストファイルを設計しました。)

私はcatを使ってファイルの各行を読み、各行をパイプラインの次のコマンドに送信できると思いました。

cat tabfile | cut -c -80

ところで、これが壊れているようです。私はいたずらを打ったし、grepが動作しているようだった。しかし、そうではないことがわかりました(ファイルのすべての行に80文字以上の文字があるわけではありません)。タブが切り捨てられ、単一文字としてカウントされるようです。

私は試した:

cat tabfile | tr \t \040 | cut -c -80

空白の読みやすさを排除することでデータがわずかに破損しますが。しかし、それはうまくいきませんでした。いいえ:

cat tabfile | tr \011 \040 | cut -c -80

たぶん私は誤ってtrを使っていますか?以前に複数のスペースを削除しようとしたときにtrに問題があったことがあります。 (このコンピュータからアクセスできるtrバージョンには、複数の文字を圧縮するための-sオプションがあるようです。これを使用する必要があるかもしれません。)

私がいたずらをしたら、Perlやawk、sedなどを使ってこれを行うことができると確信しています。

しかし、可能な限り移植性があるように(POSIX?)一般的なコマンドを使用する解決策が必要です。 trを使用すると、最終的にタブを文字に変換し、計算を実行し、計算を切り取り、その文字をもう一度タブに変換して出力しようとすることができます。

1行で入力するか、コマンドラインに直接入力する必要はありません。スクリプトを使用してください。


タブファイルに関する追加情報:

いつかはデータを別のプログラムにインポートしたいかもしれないので、タブを使ってフィールドを区別しています。したがって、コンテンツ間にタブが1つしかない傾向があります。ただし、プレーンテキストファイルを表示するときに読みやすくするために、タブを使用してコンテンツを縦列に並べ替えることもできます。つまり、特定のテキスト部分の場合、タブが次のフィールドを上下のフィールドと揃える点に達するまで、内容の末尾にスペースを埋めます。

DarkTurquoise #00CED1 海、空、漕ぎボート自然
MediumSpringGreen #00FA9A 木に魔法を使う  
ライム#00FF00春チキンとフルーツのみ$

答え1

expand私の考えでは、あなたはあなたが探しているようですunexpand\tab幅が単一文字ではなく8文字で計算されるようにしたいようです。fold同じことを行いますが、入力を切り捨てるのではなく、次の行に折り返します。私の考えでは、あなたが望むもの:

expand < input | cut -c -80

expandそしてunexpandPOSIXの指定:

  • このexpandユーティリティは、ファイルまたは標準入力を標準出力に書き込み、\tab文字を1つ以上の文字に置き換える必要があります。スペース次のタブストップまでパディングするために必要な文字です。どのバックスペースキー文字は出力にコピーし、タップ停止計算の列位置の数を減らす必要があります。

とても簡単です。それでは、それが何をしているのか見てみましょう。

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

上部のループはuntil次のデータセットを取得します。

1 1 2 2 3 3 ...

printfarg パディングフラグを使用するので、%*sセット内の各引数に対して引数の数だけprintf空白が埋められます。\tそれぞれにab文字を追加します。

すべてはtee、適用時に各フィルタの効果を表示するために使用されます。

効果は次のとおりです。

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

行は次のように2つのグループに配置されます。

  1. 出力printf ...; echo
  2. tr ...またはの出力expand
  3. 出力cut
  4. 出力wc

最初の4行はtrフィルタの結果です。ここで、各\tabは単一に変換されます。スペース

そして最後の4つのチェーン結果ですexpand

答え2

タブは分離ではなく整列に適しているため、1つのアプローチはcolumn以下を使用することですcut

column -s '\t' -t <some-file | cut -c -80

POSIXではないようですcolumn。これはUbuntuのBSDユーティリティの一部なので、かなりクロスプラットフォームであると仮定します。

答え3

コメントのDonの提案は良いスタートです。

これが(主に)動作するようにするために必要なものです。

pr +1 -1 -t -m -l1000 -w 80 tabfile

単一の列にフラグを適用する-m必要があります。-wマニュアルページでは、これを示すためにいくつかの書き換えを使用できます。

回避策を試している間に文字をpr出力して入力すると、同じ問題が発生することがわかりました。\tcut

-1(列フラグ)はマニュアルページで指定されています.

このオプションは-mで使用しないでください。

ただし、このオプションを使用しないと、行は指定されたpr長さよりはるかに短くランダムに切り捨てられます。

prまた、フィールドのすべての単語の前(または後に?)にスペースを挿入します(つまり、どこにもスペースがあり、処理後にスペースが2つあります)。単語が多すぎると、挿入されたスペースは-w制限を無視します(改行の生成)。ただし、奇妙なことに、タブで区切られていない(空白の並べ替えなど)、「列」は整列されたままです。

答え4

ディスプレイの幅を実際に理解する必要があるユーティリティの1つは次のとおりですfold。残念ながら、ラップの代わりに廃棄するオプションはないようです。非常に非効率的かもしれませんが、次のことができます。

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file

関連情報