42

仅当文件不存在时,我才想在文件末尾添加换行符。这是为了防止文件末尾出现多个换行符。

我希望使用sed. 以下是我在当前代码中遇到的问题:

sed -i -e '/^$/d;$G' /inputfile

echo file1
name1
name2

echo file2
name3
name4
(newline)

当我在文件上运行我的代码时;

echo file1
name1
name2
(newline)

echo file2
name3
name4

如果没有换行符,它会添加一个换行符,但如果存在则将其删除......这让我感到困惑。

4

8 回答 8

42

sed

GNU:

sed -i '$a\' *.txt

操作系统:

sed -i '' '$a\' *.txt

$解决最后一行。a\是附加功能。

OS X 的 sed

sed -i '' -n p *.txt

-n禁用打印并p打印图案空间。p在 OS X 的 sed 中添加了一个缺少的换行符,但在 GNU sed 中没有,所以这不适用于 GNU sed。

awk

awk 1

1可以替换为任何计算结果为真的东西。就地修改文件:

{ rm file;awk 1 >file; }<file

重击

[[ $(tail -c1 file) && -f file ]]&&echo ''>>file

从命令替换的结果中删除尾随换行符,因此只有以换行符结尾或为$(tail -c1 file)空时才为空。如果为空则为假。相当于在 bash 中。file-f filefile[[ $x ]][[ -n $x ]]

于 2013-04-24T17:45:52.363 回答
13

与其用 see 处理整个文件,只是在末尾添加换行符,只需检查最后一个字符,如果它不是换行符,则追加一个。换行的测试有点有趣,因为 shell 通常会从字符串的末尾修剪它们,所以我附加“x”来保护它:

if [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
    echo "" >>"$inputfile"
fi

请注意,这会将换行符附加到空文件中,这可能不是您想要的。如果您想单独保留空文件,请添加另一个测试:

if [ -s "$inputfile" ] && [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
    echo "" >>"$inputfile"
fi
于 2012-04-10T02:37:43.053 回答
8

因为如果它不存在它会删除换行符,你可以简单地使用:

echo "" >> file;  sed -ie '/^$/d;$G' file; sed -ie '/^$/d;$G' file

添加换行符并删除所有内容,然后添加换行符。不是优雅的方式,但肯定有效:)

于 2012-04-10T02:18:12.773 回答
3
tail -c1 file | read -r _ || echo >> file

将文件的最后一个字符通过管道输入read,如果在换行符之前遇到 EOF ,它将以非零退出代码退出(因此,如果文件的最后一个字符不是换行符)。如果read退出非零,则在文件上附加一个换行符echo(如果read退出 0,则满足||,因此该echo命令不运行)。

来自http://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/

于 2016-01-18T22:56:15.337 回答
2

使用 awk :

awk '/^$/{f=1}END{ if (!f) {print "\r"}}1' inputfile

匹配空行^$(就像你做的那样)并设置一个标志。如果最后没有设置标志,则放置换行符。

注意:这\r是在 OS X 中。\n用于其他。

于 2012-04-10T02:54:00.490 回答
1

尝试使用viex

ex -scwq foo.txt

或多个文件:

vi -es +"bufdo wq" *.txt
ex -s +"bufdo wq" *.txt

如果丢失,它会在文件保存时自动在 EOF 处添加 EOL。

要递归地申请某些文件,请使用新的通配选项( **),例如**/*.txt(enable by shopt -s globstar)。

于 2015-05-16T20:21:12.100 回答
1

仅使用 Bash

您可以将命令替换(删除尾随换行符)与 Here Strings(附加换行符)一起使用:

   Command Substitution
       Command substitution allows the output of a command to replace the command  name.   There  are  two
       forms:

          $(command)
       or
          `command`

       Bash  performs  the expansion by executing command in a subshell environment and replacing the com-
       mand substitution with the standard output of the command,  with  any  trailing  newlines  deleted.
       Embedded newlines are not deleted, but they may be removed during word splitting.  The command sub-
       stitution $(cat file) can be replaced by the equivalent but faster $(< file).



   Here Strings
       A variant of here documents, the format is:

          [n]<<<word

       The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command sub-
       stitution,  arithmetic expansion, and quote removal.  Pathname expansion and word splitting are not
       performed.  The result is supplied as a single string, with a newline appended, to the  command  on
       its standard input (or file descriptor n if n is specified).

以下是它的工作原理:

cat <<<"$(<inputfile)"

输出到文件:

cat <<<"$(<inputfile)" >outputfile

如果您需要inputfileoutputfile要使用相同的文件名,您有几个选项 - 使用sponge命令,使用更多命令替换保存到临时变量,或保存到临时文件。


使用 Sed

其他人建议使用

sed '$a\' inputfile

最后一行没有附加任何内容。这很好,但我认为

sed '$q' inputfile

更清楚一点,因为它在最后一行退出。或者你可以做

sed -n 'p'

它用于-n抑制输出,但使用p.

在任何这些情况下,sed将修复行并添加换行符,至少对于 GNU 和 BSD sed。但是,我不确定此功能是否由 POSIX 定义。的一个版本sed可能只是跳过你的行而没有换行,因为一行被定义为

零个或多个非字符加上一个终止字符的序列。

于 2018-12-15T06:33:05.580 回答
0

我通过使用dos2unix(或对应物)与--newline标志解决了这个任务。优点是这些工具可以自行检测二进制文件。我喜欢这个解决方案,tail -c1但事先过滤二进制文件对我来说真的很慢。

dos2unix --newline my_file.txt

最终,我编写了一个脚本来搜索我的项目目录,将除文件 ( , ) 之外的所有文件转换为LF( ),并使用标志通过一次调用来正确获取换行符。dos2unix*.cmdCRLFunix2dos

于 2014-10-22T13:11:40.910 回答