
次のような興味深いコマンドを見つけました:
grep -v '^>' test.fasta | tr -d '\n' | sed -e 's/\(.\)/\1\n/g' | sort | uniq -c | sort -rn
私はそれが何を意味するのか(テキスト ファイルから文字を数える)をある程度理解していますが、私の質問は次の点についてです。
sed -e 's/\(.\)/\1\n/g'
これは 3 つの置換コマンドで構成されていることはわかっています。1 つは改行を置換するもの ( \n
)、もう 1 つは改行以外の任意の文字に一致するもの ( ) ですが、 ?\(.\)
がよくわかりません。/\1\
答え1
コマンド
sed -e 's/\(.\)/\1\n/g'
は、すべての文字をその文字自体に置き換え、その後に改行文字が続く単一の GNUsed
置換コマンドです。これにより、入力が単一の文字の 1 列に折り畳まれます。
$ echo hello | sed -e 's/\(.\)/\1\n/g'
h
e
l
l
o
は\(.\)
「キャプチャ グループ」であり、1 つの文字をキャプチャします。 は\1
最初のキャプチャ グループへの「後方参照」です。\1
を置換テキストで使用すると、最初の括弧でキャプチャされたものが挿入されます。
バックスラッシュをあまり使わずに次のように書くこともできます。
sed 's/./&\n/g'
ここで、&
単に「表現に一致したもの」を意味します。
このsed
コマンドは GNUsed
標準を必要とし、このようsed
にして改行を挿入することはできません\n
。
標準ツールでより効率的に行うには、
fold -w 1
代わりに、入力内の各文字に対して正規表現のマッチングを行う必要がないため、より効率的です。
を使用するとfold
、パイプラインは次のように記述できます。
grep -v '^>' file | tr -d '\n' | fold -w 1 | sort | uniq -c | sort -rn
あるいは、awk
パイプラインのいくつかのステップを削除するために、
awk '!/^>/ { for (i = 1; i <= length; ++i) count[substr($0,i,1)]++ }
END { for (ch in count) print count[ch], ch }' file |
sort -rn
このawk
コードは、各文字が出現した回数をカウントします。これは、count
入力ストリーム内の各文字に対応する配列の値を増分することによって行われます。入力の最後に、カウントされた回数と文字数の概要が出力されます。
答え2
これでより明確になったと思います。
「3つの代替コマンドで構成されていることはわかっています」
これは単なる 1 つの代替コマンドです (コマンドを参照している場合sed
)。s/<pattern to search>/<replacement>/
これは以下を実行します。
- 各行で を検索し
<pattern>
、 に置き換えます<replacement>
。 - 旗
g
の意味はやれグ局所的にデフォルトではsed
の最初の出現部分のみが置き換えられるためです<pattern>
。
「でも、私は迷っています
/\1\
」
パターンをキャプチャするには、エスケープされた括弧で囲むか、オプション\(<pattern>\)
を使用して括弧のみを使用します。-E
(<pattern>)
セクションでは、<replacement>
このキャプチャされたパターンはバックスラッシュと数字で参照されます。\<number>
数字はキャプチャの位置を示します。複数のキャプチャがある場合があるためです。
sed -E '/(<first capture>)(<second capture>)/\1\2/'
したがって、コマンドのsed -e 's/\(.\)/\1\n/g'
意味は次のとおりです。
- すべての文字をキャプチャし
\(.\)
、それをそれ自体と新しい行に置き換えます\1\n
。 - では
g
、最初の出現で停止せずに、グローバルに実行します。
例えば:
$ echo foo | sed -E 's/(.)/\1\n/g'
f
o
o
複数のコマンドを連結する場合を除き、ここでオプション-e
は必要ありませんsed
: sed -e '...' -e '...'
、など。
詳細は以下をご覧ください。後方参照と部分式。
答え3
Raku (旧称 Perl_6) の使用
raku -e 'for lines.grep({ !/ ^ \> / }).join { .say for .comb.Bag.sort(*.values).reverse};'
サンプル入力:
>sp|P01308|INS_HUMAN Insulin OS=Homo sapiens OX=9606 GN=INS PE=1 SV=1
MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAED
LQVGQVELGGGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN
サンプル出力:
L => 20
G => 12
A => 10
E => 8
Q => 7
P => 6
C => 6
V => 6
R => 5
S => 5
Y => 4
F => 3
T => 3
N => 3
M => 2
D => 2
K => 2
I => 2
W => 2
H => 2
あなたが提示するコードは、さまざまな言語 ( だけではないsed
) で記述できますが、そのどれかがあなたの心に響くかもしれません。たとえば、上記のコードは、Perl ファミリーの言語の 1 つである Raku で書き直されています。
Raku コードのほとんどは、かなり自明です。lines
が読み込まれ、行頭の「大なり」角がない場合grep
は -pedされ、 -ed されます。結合された行は-ed (個別の文字に分割されます)、-ged (存在する各文字は になり、出現回数は としてカウント/記録されます)、出現回数が最も多いものを先頭に配置するために-ed され、 で印刷されます。!
^
>
join
comb
Bag
key
values
sort
reverse
say