仅当换行不存在时才添加换行符

时间:2012-04-10 02:01:19

标签: linux bash sed newline

我想在文件末尾添加换行符,如果它不存在,这是为了防止文件末尾有多个换行符。

我希望使用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

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

8 个答案:

答案 0 :(得分:34)

SED

GNU:

sed -i '$a\' *.txt

OS X:

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可以替换为评估为true的任何内容。修改文件:

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

的bash

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

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

答案 1 :(得分:8)

而不是处理整个文件,只需要在最后添加换行符,只需检查最后一个字符,如果换行符,请附加一个。测试换行有点有趣,因为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

答案 2 :(得分:6)

由于它删除了换行符,如果它不存在,你可以简单地使用:

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

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

答案 3 :(得分:2)

使用awk:

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

匹配空行^$(就像你一样)并设置一个标志。如果未在末尾设置标记,请放置换行符。

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

答案 4 :(得分:1)

read

获取文件的最后一个字符将其管道输入read,如果在换行符之前遇到EOF,则会以非零退出代码退出(因此,如果文件的最后一个字符不是换行符)。如果echo退出非零,则使用read将新行添加到文件中(如果||退出0,则满足echo,因此var array = []; for ( var row = 0; row < tablerows; ++row ) { var tablerow = element.getRow(row) array[row] = []; for ( var cell=0; cell < tablerow.getNumCells(); ++cell) { var celltext = tablerow.getChild(cell).getText(); array[row][cell] = celltext; } } Logger.log(JSON.stringify(array)); // debug 命令不是不跑。

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

答案 5 :(得分:0)

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

dos2unix --newline my_file.txt

最后我编写了一个搜索我的项目目录的脚本,将所有文件转换为LFdos2unix)除了*.cmd个文件(CRLFunix2dos)并使用该标志通过一次调用获得新行。

答案 6 :(得分:0)

尝试使用viex

ex -scwq foo.txt

或多个文件:

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

如果缺少文件保存,会自动在EOF处添加EOL。

要递归申请某些文件,请使用a new globbing option**),例如**/*.txtshopt -s globstar启用)。

答案 7 :(得分:0)

仅使用Bash

您可以使用“命令替换”(删除尾随的换行符)和“这里的字符串”(附加换行符):

   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的一个版本可能会跳过您的行而没有换行符,因为行定义为

  

A sequence of zero or more non- characters plus a terminating character.