どのコマンドがタブ区切りのテキストファイルをフィードし、各行を80文字にカットしますか?


8

(時々)タブ区切りデータの複数行のテキストファイルを持っています。ファイルを一目で確認できるようにファイルを出力したいので、各行の最初の80文字だけを表示したいと思います(各行の最初に重要なものを置くようにテキストファイルを設計しました)。

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

cat tabfile | cut -c -80

しかし、それは壊れているように見えました。あちこち試してみたところ、grepは機能しているように見えましたが、機能していないことがわかりました(ファイルのすべての行に80文字以上あるわけではありません)。タブは、カットによって1文字として数えられるようです。

私は試した:

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春のニワトリとfru $でのみ使用

タブ幅を数える80文字が必要ですか?タブを適切な数のスペースに置き換えてから、cutを使用できます。
muru 2014

Annnnnd、単一の文字を複数の文字で(簡単に)拡張するにはどうすればよいですか?または、より重要なのは、(行にある他の文字の数に応じて)可変の文字数を使用することです。タブを使用して、各タブの前後に異なる量の情報を縦に並べます。私が言ったように、私は学びたいと思った場合のperl / awkは/ SED私は私ができると確信しているが、私は何かのシンプルたい
user3082

あなたは試みることができるprからcoreutilspr -1 -t -l200 -W80 file-l必要に応じて、ページの長さ(の後の数)を増減します。
don_crissti 14

ドン、あなたの提案(なぜそれが答えではないのですか?)は素晴らしいエラーメッセージを私に与えます。しかし、男は「pr-印刷ファイル」と言うので、それを調べます。
user3082 14

ドン、これを答えにして、そこで議論しましょう。私はあなたのように見えるものを持っています-ほとんど同じフォーマット、ほとんど同じフラグ:-Wの代わりに-wなど...
user3082

回答:


9

探しているexpandと思いますunexpand\tabの幅を1文字ではなく8文字としてカウントしようとしているようです。foldそれも同様に行いますが、入力を切り捨てるのではなく、次の行に折り返します。私はあなたが望むと思います:

expand < input | cut -c -80

expandそしてunexpand両方ともPOSIXは、指定されました

  • expandユーティリティは、ファイルを書き込むものかと標準入力を標準出力に\tABの文字が一つ以上で置き換えられた空間の次のタブストップにパッドに必要な文字。任意のバックスペース文字は出力にコピーされ、減算されるタブストップの計算のためのカラム位置の数を引き起こすなければなりません。列位置カウントはゼロ未満にデクリメントされません。

ものすごく単純。それで、これが何をするかを見てみましょう:

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 ...

それはprintfでこれをsの%*s引数のパディングフラグセットにおけるそれらのそれぞれのためにそれほどprintf多くのスペースがAS引数の数であるようにとの意志パッド。それぞれに\tab文字を追加します。

すべてのは、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が1つのスペースに変換されます

そして、下の4つはexpandチェーンの結果です。


1
\ tは8(?5)または1つとしてカウントされている場合、実際に、それは1としてカウントされ、8として表示されていないだけであること、(あまり)気にしない
user3082

+ @ anon3202-完全に理にかなっています。私はあなたの意味を理解しています- (そして、タブストップの長さはcliオプションです) -私はそれを私が言うことができるほど上手く言っていませんでした。うまくいけば、あなたはその要点を理解できます。
mikeserv 2014

説明には完全には従いませんでしたが、エキスパンドショーを見て回るのは間違いなく私が探していたものです。
user3082 2014

3

タブは区切りよりも整列のためのものであるため、1つの方法としてcolumn、次のように使用しますcut

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

columnPOSIXではないようです。UbuntuのBSDユーティリティの一部であるため、かなりクロスプラットフォームであると思います。


columnこの方法を使用すると、OPを配置するために手動でスペースを追加する必要さえありません。
Beni Cherniavsky-Paskin

1

コメントでドンの提案は良いスタートでした。

これは(ほとんど)それを機能させるために必要なものです:

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

-m作るために必要だった-w単一の列にフラグテイク効果を。マニュアルページは、それを示すためにいくつかの書き換えを使用できます。

回避策を試したところ、文字がpr出力されることがわかりました。\tその結果をフィードするcutと、同じ問題が発生しました。

-1 (列フラグ)は特にmanページで次のように述べています:

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

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

prまた、フィールド内のすべての単語の前(または後?)にスペースを挿入します(つまり、1つのスペースがあるすべての場所、処理後は2つのスペースがあります)。単語が多すぎる場合、挿入されたスペースは-w制限を無視します(折り返しの作成)。しかし、奇妙なことに、タブで区切られていない(つまり、空白が配置されている)「列」は整列したままです。



0

ディスプレイの幅を正確に認識する必要のあるユーティリティの1つはfold、残念ながら、折り返すのではなく破棄するオプションがないようです。恐ろしく非効率的ですが、次のようなこともできます

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.