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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10082204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:41:52  来源:igfitidea点击:

Add a newline only if it doesn't exist

linuxbashsednewline

提问by AlwynIsPat

I want to add a newline at the end of a file only if it doesn't exists, this is to prevent multiple newlines at the end of the file.

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

I'm hoping to use sed. Here's the issues i'm having with my current code:

我希望使用 sed。这是我当前代码的问题:

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

echo file1
name1
name2

echo file2
name3
name4
(newline)

when i run my code on to the files;

当我将代码运行到文件上时;

echo file1
name1
name2
(newline)

echo file2
name3
name4

it adds a newline if it doesnt have but removes if it exists... this puzzles me..

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

采纳答案by P.P

Since it removes newline if it's not there, you could simply use:

由于它在不存在时删除换行符,因此您可以简单地使用:

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

Adds a newline and removes everything then adds newline. Not the elegant way, but certainly works :)

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

回答by Gordon Davisson

Rather than processing the whole file with see just to add a newline at the end, just check the last character and if it's nota newline, append one. Testing for newline is slightly interesting, since the shell will generally trim them from the end of strings, so I append "x" to protect it:

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

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

Note that this will append newline to empty files, which might not be what you want. If you want to leave empty files alone, add another test:

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

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

回答by ring bearer

Using awk :

使用 awk :

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

Match blank line ^$(just like you did) and set up a flag. If flag is not set at the end, place newline character.

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

Note: that \ris in OS X. Use \nfor other.

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

回答by Lri

sed

sed

GNU:

GNU:

sed -i '$a\' *.txt

OS X:

操作系统:

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

$addresses the last line. a\is the append function.

$地址最后一行。a\是追加函数。

OS X's sed

OS X 的 sed

sed -i '' -n p *.txt

-ndisables printing and pprints the pattern space. padds a missing newline in OS X's sed but not in GNU sed, so this doesn't work with GNU sed.

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

awk

awk

awk 1

1can be replaced with anything that evaluates to true. Modifying a file in place:

1可以用任何评估为真的东西替换。就地修改文件:

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

bash

猛击

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

Trailing newlines are removed from the result of the command substitution, so $(tail -c1 file)is empty only if fileends with a linefeed or is empty. -f fileis false if fileis empty. [[ $x ]]is equivalent to [[ -n $x ]]in bash.

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

回答by Daniel B?hmer

I solved this task by using dos2unix(or counterparts) with the --newlineflag. The advantage is that these tools detect binary files on their own. I like the solution with tail -c1but filtering binary files beforehand has been reallyslow for me.

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

dos2unix --newline my_file.txt

Eventually I wrote a script that searched my project directory, converted all files to LF(dos2unix) except *.cmdfiles (CRLF, unix2dos) and used the flag to get the newlines right with one call.

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

回答by kenorb

Try using vior ex:

尝试使用viex

ex -scwq foo.txt

or for multiple files:

或者对于多个文件:

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

which automatically adds EOL at EOF on file save if it's missing.

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

To apply for certain files recursively, use a new globbing option(**) such as **/*.txt(enable by shopt -s globstar).

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

回答by Isaac

tail -c1 file | read -r _ || echo >> file

gets the last character of the file pipes it into read, which will exit with a nonzero exit code if it encounters EOF before newline (so, if the last character of the file isn't a newline). If readexits nonzero, then append a newline onto the file using echo(if readexits 0, that satisfies the ||, so the echocommand isn't run).

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

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

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

回答by dosentmatter

Using Bash only

仅使用 Bash

You can use Command Substitution (remove trailing newlines) with Here Strings (appends newline):

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

   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).

Here's how it works:

这是它的工作原理:

cat <<<"$(<inputfile)"

Output to file:

输出到文件:

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

If you need inputfileand outputfileto be the same file name, you have a couple options - use spongecommand, save to temporary variable with more command substitution, or save to temporary file.

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



Using Sed

使用 Sed

Others have suggested using

其他人建议使用

sed '$a\' inputfile

which appends nothing to the last line. This is fine, but I think

最后一行不添加任何内容。这很好,但我认为

sed '$q' inputfile

is a bit clearer, because it quits on the last line. Or you can do

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

sed -n 'p'

which uses -nto suppress output, but prints it back out with p.

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

In any of these cases, sedwill fix up the line and add a newline, at least for GNU and BSD sed. However, I'm not sure if this functionality is defined by POSIX. A version of sedmight just skip your line without a newline since a line is defined as

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

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

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