如何在使用 wc -m 计算多个文件的字符时忽略 '\r'

How to ignore '\r' while counting characters of several files with wc -m

我尝试计算作者“JohnJohnson”使用此命令提交给 git 的字符数:

wc -m $(git log --use-mailmap --no-merges --author="JohnJohnson" --name-only --pretty=format:"" | sort -u)

问题是在 Linux 和 Windows(git-bash) 上它产生不同的结果,至少因为在 Windows 上新的行由两个字符“\r\n”组成。有没有办法让 wc -m 忽略 '\r' 以便我使用相同的命令在两个操作系统上获得一致的结果?

注意: 虽然 运行 wc -m 之前每个文件上的 运行 dos2unix 应该足够了,但我假设) dos2unix 不可用 and/or b) OP 可能会发现还有其他字符(除了 \r)需要删除。


假设 objective 是生成 wc -m 完全相同的输出 ,一个使用用户定义函数的想法:

my_wc () {
    local charcount=0 totcount=0

    for fname in $@
    do
        charcount=$(tr -d '\r' < $fname | wc -m)
        echo "$charcount $fname" 
        ((totcount+=charcount))
    done

    echo "$totcount total"
}

应用于OP的例子:

my_wc $(git log --use-mailmap --no-merges --author="JohnJohnson" --name-only --pretty=format:"" | sort -u)

如果 OP 找到要跳过的其他字符(\r 除外),则将它们添加到 tr -d '\r' 调用中。


另一个函数想法,但这个使用 awk:

my_wc() {
    awk 'BEGIN { RS="^$" }                  # whole file becomes one single, long record
               { gsub("\r","")
                 n=length([=12=])
                 tot+=n
                 print n,FILENAME
               }
         END   { print tot,"total"}' $@
}

在几个示例文件上演示这些函数:

$ head f?
==> f1 <==
a       13
a       5
b       7
a       20
a       3

==> f2 <==
a       13
a       5
b       7
a       20
a       3

==> f3 <==
a       13
a       5
b       7
a       20
a       3

$ dos2unix f?

$ wc -m f?
22 f1
22 f2
22 f3
66 total

$ unix2dos f?

$ wc -m f?
27 f1
27 f2
27 f3
81 total

$ my_wc f?
22 f1
22 f2
22 f3
66 total

在配置为在您的工作树中不进行换行转换的存储库中运行,即关闭 eol 处理。您可以在任何地方执行此操作,例如 git config core.eol false。避免干扰的最简单方法可能是在临时克隆中执行此操作,

git clone -ns . `mktemp -d`; cd $_
git config core.eol false
git checkout

现在您得到了原始结帐,没有应用 eol munging。