(場合によっては)タブ区切りのデータの複数行のテキストファイルがあります。ファイルを一目で確認できるように出力したいので、各行の最初の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つしかない傾向があります。ただし、プレーンテキストファイルを見たときに読みやすくするために、タブを使用して縦の列に揃えています。つまり、一部のテキストでは、次のフィールドを上下に並べてタブが機能する場所に到達するまで、コンテンツの最後にスペースを埋め込みます。
DarkTurquoise#00CED1海、空、手漕ぎボート自然 MediumSpringGreen#00FA9A樹木に便利マジック ライム#00FF00春の鶏とフル$ でのみ使用
expand
および/またはunexpand
を探していると思います。 \t
abの幅を1文字ではなく8文字としてカウントしようとしているようです。 fold
もそれを行いますが、入力を切り捨てるのではなく、次の行にラップします。私はあなたが望むと思います:
expand < input | cut -c -80
expand
とunexpand
は両方とも POSIXを指定 :
expand
ユーティリティは、ファイルまたは標準入力を標準出力に書き込み、\t
ab文字を1つ以上のスペースに置き換えます。次のタブストップにパディングするために必要な文字。 backspace文字はすべて出力にコピーされ、タブストップ計算の列位置カウントがデクリメントされます。列位置カウントはゼロ未満にデクリメントされません。ものすごく単純。だから、これが何をするのか見てみましょう:
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 ...
これは%*s
引数パディングフラグでprintf
sされるため、セット内の各printf
は、引数の数と同じ数のスペースでパディングされます。それぞれに\t
ab文字を追加します。
すべてのtee
sは、適用された各フィルターの効果を示すために使用されます。
そして効果はこれらです:
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つのセットに並んでいます...
printf ...; echo
の出力tr ...
またはexpand
の出力cut
の出力wc
の出力上部の4行はtr
フィルターの結果です。各\t
abは単一のspaceに変換されます。
そして、下の4つはexpand
チェーンの結果です。
タブは区切りよりも位置合わせのためのものであるため、1つの方法はcolumn
を使用してからcut
を使用することです。
column -s '\t' -t <some-file | cut -c -80
column
はPOSIXではないようです。 UbuntuのBSDユーティリティの一部であるため、かなりクロスプラットフォームであると思います。
コメントでのドンの提案は良いスタートでした。
これは私がそれを(ほとんど)動作させるために必要なものです:
pr +1 -1 -t -m -l1000 -w 80 tabfile
-m
フラグを単一の列で有効にするには、-w
が必要でした。マニュアルページはそれを示すためにいくつかの書き直しを使用できます。
回避策を試したところ、pr
が\t
文字を出力することがわかりました。その結果をcut
に供給すると、同じ問題が発生しました。
-1
(列フラグ)は、manページで具体的に次のように述べています。
このオプションは、-mと一緒に使用しないでください。
ただし、このオプションを使用しない場合、pr
は指定された長さよりはるかに短い長さで行を完全に切り捨てます。
pr
は、フィールド内のすべてのWordの前(または後)にもスペースを挿入します(つまり、1つのスペースがあるすべての場所、処理後は2つのスペースがあります)。単語が多すぎる場合、挿入されたスペースは-w
制限を無視します(ラップアラウンドを作成します)。しかし、奇妙なことに、タブで区切られていない(つまり、空白が配置されている)「列」は整列したままです。
本当に表示幅を意識する必要があるユーティリティの1つはfold
です。残念ながら、折り返す代わりに破棄するオプションがないようです。それは恐らく非効率的ですが、しかしあなたは次のようなことをすることができます
while read -r line; do fold -w80 <<< "$line" | head -n1; done < file