计算第一个 grep 结果后的行中的字符数,但从计数中删除新行

计算第一个 grep 结果后的行中的字符数,但从计数中删除新行

问题:

我有多个文本文件 (.fas),如下所示:

文件1.fas:

>species1
AICGICVIAGIAIYIAAICG
>species2
AICGIVVYICAGAYICAGCG

文件2.fas:

>species1
AIG
>species2
GCI

我感兴趣的是计算第二行中的字符数(当它们对齐时,一个文件中的所有物种都是相同的。

我目前的一张班轮:

for i in *.fas; do echo -n "$i," && grep -m 1 -A 1 '>' $i | tail -n 1 | wc -c; done;

这在一定程度上有效,但计算的数字比实际字符数高一个数字,因为它计算的是换行符。如何解决此问题,使其仅计算不包括换行符的字符数?

电流输出:

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 而不是换行数。

或者您可以awk仅使用,匹配整行并计算其字符数:

| awk '{match("[A-Z]*");print RLENGTH}'

RLENGTH是匹配的长度(这里是整行)。在这里,我假设您仅使用大写字母,否则使用.代替[A-Z]

vim(文本编辑器,因此它可能与您的脚本不兼容)上,直观地选择您的区域(一行或多行)并运行:

:'<,'>s/[A-Z]*//gn

您还可以使用以下命令删除换行符tr(也适用于多行):

| tr -d '\n' | wc -c

顺便说一句,可能还有很多其他方法可以做到这一点。

答案2

用于find查找 .fas 文件,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 单行命令,打印文件名和第二行的长度(以逗号分隔)。使用标志去除换行符-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:一次循环输入一行,$_默认将其分配给。 :在内联执行代码之前
-l剥离输入行分隔符(默认在 *NIX 上),并在打印时附加它。"\n"

$ARGV是当前输入文件的名称。
length $_是当前行的长度,已选择该行作为输入行号 2 ( $. == 2)。
last LINE使代码在打印行长度后跳到最后一个输入行,以提高速度。

也可以看看:

perlrun:命令行开关

相关内容