質問:
次のようないくつかのテキストファイル(.fas)があります。
ファイル1.fas:
>species1
AICGICVIAGIAIYIAAICG
>species2
AICGIVVYICAGAYICAGCG
ファイル2.fas:
>species1
AIG
>species2
GCI
私が興味を持っているのは、2行目の文字数を数えることです(ファイルが並べ替えられたときにファイルのすべての種類について同じです)。
私の現在の1つのライナー:
for i in *.fas; do echo -n "$i," && grep -m 1 -A 1 '>' $i | tail -n 1 | wc -c; done;
これはある程度機能しますが、計算された数字は改行文字を計算するため、実際の文字数よりも1桁高くなります。改行以外の文字のみを計算するにはどうすればよいですか?
現在の出力:
file1.fas,21
file2.fas,4
希望の出力:
file1.fas,20
file2.fas,3
答え1
| wc -l
行数を印刷します。| wc -c
改行を含む文字数を印刷します。| wc -lc
両方とも印刷します(行番号の最初)。
したがって、単に減算することができます。 (代わりに作成してください|wc -c
)
| wc -lc | awk '{print $2 - $1}'
1行だけシーケンスを印刷する場合は、改行の代わりに1を引くことができます。
あるいは、awk
行全体を一致させ、対応する文字数を計算して使用することもできます。
| awk '{match("[A-Z]*");print RLENGTH}'
RLENGTH
試合の長さです(ここではフルライン)。ここでは大文字のみを使用すると仮定します。そうでなければ.
代わりに。[A-Z]
vim
(テキストエディタなのでスクリプトと互換性がない可能性があります)で範囲(1行以上)を視覚的に選択し、次の操作を実行します。
:'<,'>s/[A-Z]*//gn
以下を使用して改行文字を削除することもできますtr
(複数行でも機能します)。
| tr -d '\n' | wc -c
ところで、これを行うには他にも多くの方法があります。
答え2
.fasファイルを見つけるために使用されるfind
findコマンドは、awkが一度にファイルを処理できるように、ファイルをawkのコマンドラインにプッシュします。したがって、awk 呼び出しの数が最小化されます。
$ find . -maxdepth 1 -type f -name '*.fas' -exec \
awk -v OFS=, 'FNR==2{print FILENAME, length();nextfile}' {} +
出力:
./file1.fas,20
./file2.fas,3
答え3
次のperl 1行コマンドを使用して、ファイル名と2行目の長さ(カンマ区切り)を印刷します。改行文字を削除するには、フラグを使用してください-l
。
for i in *.fas; do perl -lne 'if ( $. == 2) { print join ",", $ARGV, length $_; last LINE; }' $i ; done
入力する:
cat > file1.fas <<EOF
>species1
AICGICVIAGIAIYIAAICG
>species2
AICGIVVYICAGAYICAGCG
EOF
cat > file2.fas <<EOF
>species1
AIG
>species2
GCI
EOF
出力:
file1.fas,20
file2.fas,3
Perlシングルライナーは、次のコマンドラインフラグを使用します。 ::
-e
Perlにファイルではなくインラインコードを見つけるように指示します。
-n
:一度に1行ずつ入力を繰り返し、デフォルト$_
で割り当てられます。 :コードインラインを実行する前に、入力行区切り文字(* NIXのデフォルト)を削除して
-l
印刷するときに追加します。"\n"
$ARGV
現在の入力ファイルの名前。は、入力行番号2()
length $_
で選択された現在の行の長さです。速度を向上させるために行の長さを印刷した後、コードが最後の入力行にジャンプするようにします。$. == 2
last LINE
また見なさい: