BASHのマニュアルページで定義されているように、文字CLASSでランダムファイル内のすべての文字を効率的に計算する必要があります。
[[:alnum:]], [[:alpha:]], [[:ascii:]], [[:blank:]], [[:cntrl:]], [[:digit:]], [[ :図:]]、[[:下部:]]、[[:印刷:]]、[[:punct:]]、[[:Space:]]、[[:上部:]]、[[:Word :]]と[[:xdigit:]]
ファイルを処理した後、各結果の数がゼロであっても1行に表示されます。
インターネット検索では、同様のコンテンツを見つけることができませんでした。
任意のファイル(/tmp/f1.txt
)にはさまざまなテキスト/データが含まれます。
私はELFバイナリやUnicode(またはあらゆる形式のマルチバイト)コンテンツを扱いたくありません。
CR
行数(および/または)は気にせず、上記のクラスを介して累積されたターゲットファイル内LF
の各「文字」の数だけを気にします。
function()
私はこれが最終的に大きなbashスクリプト間の標準になることを意図しています。 bash/sed/awkなどが必要です。 Perl/python/rubyはあまり必要ありません。
サンプルデータファイルは次のとおりです。
0バイト、つまりコンテンツはまったくありません。
単一文字
言葉
複数の単語をスペースで区切ります。
複数行には、スペースおよび/またはキャリッジリターンおよび/または改行が含まれています。
複数行ファイルの場合、最後の行の終わりを示すか、またはがない可能性が
CR
あります(ただし、すべての文字はまだ計算する必要があります)。LF
答え1
file=myfile
for class in alnum alpha blank cntrl digit graph lower print punct space upper xdigit
do
printf '%7s: %d\n' "$class" "$(tr -Cd "[:${class}:]" < "$file" | wc -m)"
done
ascii
word
標準文字クラスではなく、具体的ですbash
。下線が引かれword
て文字 0~127 なので、次のようにできます。alnum
ascii
printf '%7s: %d\n' word "$(tr -Cd "_[:alnum:]" < "$file" | wc -m)"
printf '%7s: %d\n' ascii "$(LC_ALL=C tr -cd '\0-\177' < "$file" | wc -c)"
(coreutils-8.22以降、GNU実装はtr
マルチバイト文字と連携できません。)
少なくとも GNU libc を使用するシステムでは、以下を実行することもできます。
$ locale ctype-class-names
upper;lower;alpha;digit;xdigit;space;print;graph;blank;cntrl;punct;alnum;combining;combining_level3
そのロケールで定義されている文字クラスのリストを見つけます。
答え2
面白い授業だと思います!それは何ですか?
これにより、ほとんどの場合、sedは:ascii:または:word:をサポートしていないようです。
for f in alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
do
echo "$f: $(sed s/[^[:$f:]]//g b.txt | tr -d '\n' | wc -c)"
done
私たちはすべてを削除するためにsedを使用しますとは別に文字に興味を持ち、空白行をすべて削除し、残りの文字数を取得します。
+/-1または10倍のエラーを除いて、比較的正確でなければなりません。
答え3
どのキャラクターがどのカテゴリーに属するのかは調べません。おそらくあなたが見つけたり、他の答えを探したりするかもしれません。ただし、これによりファイル文字を失うことなく明確に表現できます。
_c2o() { od -A n -t o1 -w1 -v | tr -dc '0-9\n' ; }
_c2o <file
163
150
072
040
167
141
162
156
151
156
147
私はこの機能をさまざまな方法で使用しています。各行は、8進形式で表示されるバイトです。もちろんod
非常に設定可能です。ただし、この方法では、非常に簡単に目標値に対して行カウンタを実装できgrep
ますsed
。ケーキのかけらです。そしてそれは非常に高速です。
さて、だから私はクラスを続けました:
_classes() { set -- ${classes=alnum alpha blank cntrl digit graph lower print punct space upper xdigit}
while ${1+:} false ; do
printf %b $(printf '\\%04o\n' $(seq 0 127)) |
tr -dc "[:${1}:]" | {
printf "$1='"
_c2o
printf "'\n"
} ; shift
done
}
上記のコマンドを実行すると、次のような出力が表示されます。
xdigit='060
061
062
063
064
065
066
067
070
...
'
そこで、私は次のことを想像します。
eval "$(_classes)"
for class in $classes ; do
eval "$class=\$(_c2o <file | grep -c -F "$class")"
done
この問題をよりよく処理する必要がありますが、これはうまくいきます。