有没有办法使用Bash删除文件末尾的任何尾随空白行(只包含空格的行)?
例如,这个:
123\n\n\n12\n \n \t \n
应该成为:
123\n\n\n12\n
我知道如何在C中使用fseek()和ftruncate(),但不确定是否可以使用bash和现成的cmd-line实用程序,而无需创建专门的C程序为了它。
我已经看到一些问题,一般要求删除尾随空格,例如How to remove trailing whitespace of all files recursively?,但是我要求通过截断而不是覆盖文件来执行此操作(出于性能原因)。
答案 0 :(得分:3)
您可以使用tac
找到尾随空白行,然后使用dd
截断:
#!/bin/bash
file=$1
trailing=$(tac "$file" | sed -n '/^[ \t]*$/!q; p' | wc -c)
end=$(( $(wc -c < "$file") - trailing ))
dd bs=1 seek=$end count=0 of="$file"
答案 1 :(得分:0)
我非常喜欢@that other guy的答案。
但是,这是另一种可能性,它使用命令替换删除尾随换行的事实,并且不会读取文件两次以计算应该修剪它的位置。
#!/bin/bash
file=$1
tokeep=$(wc -c <<< "$(< "$file")") || exit $?
dd if=/dev/null of="$file" bs=1 seek=$tokeep
如果要删除尾随空格(即换行符,空格,制表符等),请使用tr
将空格替换为换行符,以便丢弃尾随空格:
#!/bin/bash
file=$1
tokeep=$(wc -c <<< "$(tr '[[:space:]]' '\n' < "$file")") || exit $?
dd if=/dev/null of="$file" bs=1 seek=$tokeep
这会保留一个尾随换行符(因为here-string <<<
会添加换行符)。如果你想修剪这个尾随换行符(但实际上你不应该!),请在seek=$tokeep
语句中用seek=$((tokeep-1))
替换dd
。
注意。 [[:space:]]
字符类依赖于语言环境。在C和POSIX语言环境中,它对应于空格,换页\f
,换行符\n
,回车\r
,水平标签\t
和垂直标签\v
(见man 3 isspace
) 1 。您也可以制作自己的一组字符:如果您只想修剪尾随的换行符和制表符,但保留所有其他空格,请使用
tr '\t' '\n'
1 这很好,因为它们都是一个字节长,但是如果您的语言环境有超过一个字节的空格(例如,一个牢不可破的空格{{1}),请不要使用它是UTF-8编码为两个字节U+00A0
)。如果不确定正在使用的语言环境,则应在C2 A0
中使用自己的字符,例如tr
,以确保它们都是一个字节长。如果您还想处理两个字节字符,则应使用两个换行符替换它们,例如使用'\t '
。具有牢不可破的空间的示例:
sed
假设您有UTF-8语言环境。这有点笨拙,可能超出了原始问题的范围。