首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否使用grep/sed递归删除文件末尾的尾随空格?

问是否使用grep/sed递归删除文件末尾的尾随空格?
EN

Stack Overflow用户
提问于 2011-01-19 01:49:07
回答 9查看 8.4K关注 0票数 1

基本上,我有大约1500个文件,其中任何一个文件的最后一个字符都不应该是任何类型的空格。

如何检查一堆文件以确保它们不会以某种形式的空格结尾?(换行符、空格、回车符、制表符等)?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-01-19 02:01:48

代码语言:javascript
复制
awk '{if (flag) print line; line = $0; flag = 1} END {gsub("[[:space:]]+$","",line); printf line}'

编辑:

新版本:

sed命令删除所有只包含空格的尾随行,然后awk命令删除结束的换行符。

代码语言:javascript
复制
sed '/^[[:space:]]*$/{:a;$d;N;/\n[[:space:]]*$/ba}' inputfile |
    awk '{if (flag) print line; line = $0; flag = 1} END {printf line}'

缺点是它读取文件两次。

编辑2:

这是一个只读文件一次的all-awk解决方案。它以类似于上面的sed命令的方式累积仅包含空格的行。

代码语言:javascript
复制
#!/usr/bin/awk -f

# accumulate a run of white-space-only lines so they can be printed or discarded
/^[[:space:]]*$/ {
    accumlines = accumlines nl $0
    nl = "\n"
    accum = 1
    next
}

# print the previous line and any accumulated lines, store the current line for the next pass
{
    if (flag) print line
    if (accum) { print accumlines; accum = 0 }
    accumlines = nl = ""
    line = $0
    flag = 1
}

# print the last line without a trailing newline after removing all trailing whitespace
# the resulting output could be null (nothing rather than 0x00)
# note that we're not print the accumulated lines since they're part of the 
# trailing white-space we're trying to get rid of
END {
    gsub("[[:space:]]+$","",line)
    printf line
}

编辑3:

  • 删除了不必要的(singular)
  • added lines to accumlines,以便更容易与line (singular)
  • added comments

区分开来

票数 3
EN

Stack Overflow用户

发布于 2011-01-19 01:59:19

这将删除所有尾随的空格:

代码语言:javascript
复制
perl -e '$s = ""; while (defined($_ = getc)) { if (/\s/) { $s .= $_; } else { print $s, $_; $s = ""; } }' < infile > outfile

可能在sed中也有类似的东西,但我对Perl更熟悉,希望它能为你工作。基本思想:如果下一个字符是空格,则将其保存;否则,打印任何已保存的字符,后跟刚读取的字符。如果我们在读取一个或多个空格字符后按EOF,它们将不会被打印。

这将简单地检测尾随的空格,如果是,则给出退出代码1:

代码语言:javascript
复制
perl -e 'while (defined($_ = getc)) { $last = $_; } exit($last =~ /\s/);' < infile > outfile

EDIT上面描述了如何检测或更改单个文件。如果您有一个包含要应用更改的文件的大型目录树,则可以将该命令放在单独的脚本中:

fix.pl

代码语言:javascript
复制
#!/usr/bin/perl
$s = "";
while (defined($_ = getc)) {
    if (/\s/) { $s .= $_; } else { print $s, $_; $s = ""; }
}

并将其与find命令结合使用:

代码语言:javascript
复制
find /top/dir -type f -exec sh -c 'mv "{}" "{}.bak" && fix.pl < "{}.bak" > "{}"' ';'

这会将每个原始文件移动到以".bak“结尾的备份文件中。(最好先在一个小的测试文件集上进行测试。)

票数 2
EN

Stack Overflow用户

发布于 2011-01-19 03:01:32

从下到上读取文件可能更容易:

代码语言:javascript
复制
tac filename | 
awk '
    /^[[:space:]]*$/ && !seen {next} 
    /[^[:space:]]/   && !seen {gsub(/[[:space:]]+$/,""); seen=1}
    seen
' | 
tac
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4727268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档