Linux 字符计数中不计算换行符

Linux 字符计数中不计算换行符,linux,shell,awk,Linux,Shell,Awk,我有以下代码,它使用awk计算文件中的字符数 但是它不计算换行符,因为它是在$wc文件中计算的 档案:abc 12345 12345 12345 12345 12345 awk命令: $ awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)c++}END{print "total chars:"c}' abc 但如果我运行与wc abc相同的abc文件,它将给我o/p作为30个字符 是否建议我一次使用两个文件分隔符?您的记录仍然用RS分隔,因此5个换行符不包括在

我有以下代码,它使用awk计算文件中的字符数
但是它不计算换行符,因为它是在
$wc文件中计算的

档案:abc

12345
12345
12345
12345
12345

awk命令:

$ awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)c++}END{print "total chars:"c}' abc
但如果我运行与
wc abc
相同的abc文件,它将给我o/p作为
30个字符


是否建议我一次使用两个文件分隔符?

您的记录仍然用RS分隔,因此5个换行符不包括在计数中

对FS和RS使用另一个分隔符,并计算整个$0的长度:

awk 'BEGIN{FS=RS="\x1c"}{c+=length($0)}END{print "total chars:"c}' abc
输出:

total chars:30
请注意,使用
“\x00”
将使其跳过最后一个字符

从概念上讲,它实际上与:

awk 'BEGIN{FS=RS="\x1c"}END{print "total chars:" length($0)}' abc

假设该文件不包含任何
\x1c
。不管怎样,如果有,它仍然是无效的。

您的记录仍然用RS分隔,因此5个换行符从计数中排除

对FS和RS使用另一个分隔符,并计算整个$0的长度:

awk 'BEGIN{FS=RS="\x1c"}{c+=length($0)}END{print "total chars:"c}' abc
输出:

total chars:30
请注意,使用
“\x00”
将使其跳过最后一个字符

从概念上讲,它实际上与:

awk 'BEGIN{FS=RS="\x1c"}END{print "total chars:" length($0)}' abc

假设该文件不包含任何
\x1c
。无论如何,如果有,它都是无效的。

就像我在这篇文章中提到的:
awk
只能为正确的文本文件提供正确的结果,在这些文件中,可以观察到最大行长度等限制,最后一行以换行结束,而wc没有这个限制

awk '{t+=length} END{print "Total chars: " NR+t}' file
wc
不在乎,只会计算字符数

==编辑=== 这可能会奏效:

awk '
  NR==FNR{
    m++
    next
  }
  {
    t+=length
  }
  m==FNR-1{
    RS="§"
  }
  END{
    print "Total chars: " FNR+t-1
  }
' file file
或者在一行中:

awk 'NR==FNR{ m++; next } { t+=length } m==FNR-1{ RS="§" } END{ print "Total chars: " FNR+t-1 } ' file file

该文件被读取两次以确定行数,然后在第二次读取时,记录分隔符被更改。

正如我在本线程中指出的:
awk
只能为正确的文本文件提供正确的结果,其中遵守了最大行长度等限制,最后一行以换行结束,鉴于wc没有此限制

awk '{t+=length} END{print "Total chars: " NR+t}' file
wc
不在乎,只会计算字符数

==编辑=== 这可能会奏效:

awk '
  NR==FNR{
    m++
    next
  }
  {
    t+=length
  }
  m==FNR-1{
    RS="§"
  }
  END{
    print "Total chars: " FNR+t-1
  }
' file file
或者在一行中:

awk 'NR==FNR{ m++; next } { t+=length } m==FNR-1{ RS="§" } END{ print "Total chars: " FNR+t-1 } ' file file

读取文件两次以确定行数,然后在第二次读取时更改记录分隔符。

这是基于@Scrutnizer的解决方案,以显示处理可能不以换行结束的文件的一种方法(使用GNU awk表示
RT
)来解决@konsolebox的问题:

gawk '{t+=length+(RT?1:0)} END{print t}' file
或者,更有效地说,正如@konsolebox所指出的:

gawk '{t+=length} END{print t+NR-(RT?0:1)}' file
要容纳空文件,请执行以下操作:

gawk '{t+=length}END{print t+NR-(!RT&&NR?1:0)}'

这是基于@Scrutnizer的解决方案,该解决方案展示了一种处理可能不以换行符结尾的文件的方法(使用GNU awk for
RT
),以解决@konsolebox的问题:

gawk '{t+=length+(RT?1:0)} END{print t}' file
或者,更有效地说,正如@konsolebox所指出的:

gawk '{t+=length} END{print t+NR-(RT?0:1)}' file
要容纳空文件,请执行以下操作:

gawk '{t+=length}END{print t+NR-(!RT&&NR?1:0)}'


@sudo_O我在等你专业…我不明白你所说的
是什么意思。我是否可以一次使用两个文件分隔符?
:什么是
文件分隔符
?需要两个文件分隔符与你计算字符的问题有什么关系?@sudo_O我在等你专业…我不明白你所说的
是什么意思。是否可以一次使用两个文件分隔符?
:什么是
文件分隔符
?需要其中两个与您计算字符的问题有什么关系?这对小文件有效,但最终可能导致记录太长的错误。不同的AWK以不同的方式处理这个问题。@scrutnizer它在gawk、mawk和nawk中的作用是相同的。它的行为会有什么不同?当然每个人都能读到,但我不确定是否还有其他更简单但仍然一致的解决方案。@konsolebox正如您前几天在一个不同的线程中注意到的,nawk中有一个最大缓冲区大小。每个awk也一样,但每个awk的值不同。您告诉awk将整个文件作为一条记录的一个字段来读取,因此对于大文件,它在每个awk的某个点都会失败,每个awk的点都会不同。@EdMorton,这是显而易见的。我知道,即使在我年轻的时候,我也只是在编写代码。但有什么解决办法能比这更好呢?此外,这个例子不是关于大文件的,我只是在证明一个概念。不应该从中提取任何严重的内容。@EdMorton是的,我正在考虑awks将如何处理语法抱歉。这对小文件有效,但最终可能导致记录太长的错误。不同的AWK以不同的方式处理这个问题。@scrutnizer它在gawk、mawk和nawk中的作用是相同的。它的行为会有什么不同?当然每个人都能读到,但我不确定是否还有其他更简单但仍然一致的解决方案。@konsolebox正如您前几天在一个不同的线程中注意到的,nawk中有一个最大缓冲区大小。每个awk也一样,但每个awk的值不同。您告诉awk将整个文件作为一条记录的一个字段来读取,因此对于大文件,它在每个awk的某个点都会失败,每个awk的点都会不同。@EdMorton,这是显而易见的。我知道,即使在我年轻的时候,我也只是在编写代码。但有什么解决办法能比这更好呢?此外,这个例子不是关于大文件的,我只是在证明一个概念。不应该从中提取任何严重的内容。@EdMorton是的,我在考虑awks将如何处理语法抱歉。这与不以换行符结尾的行不一致。@konsolebox:这就是我所说的(最后一行可能是默认的RS).@konsolebox:我用标准awk添加了另一种可能性(未使用gawk的
RT
)我尝试了您的更新。很抱歉,它似乎无法很好地计算换行。它返回
-1
,并且文件没有任何记录。buf也没有可能的问题