无法将一个文件中的字符串放在另一个文件的字符串下

无法将一个文件中的字符串放在另一个文件的字符串下

我在使用命令连接文件时遇到了一个奇怪的问题cat。我有两个文件,每个文件中都有一个字符串:

文件1:

ABC

文件2:

DEF

要么我做cat file1 file2,要么我做cat file1 >> file2。我期望输出如下所示:

ABC  
DEF

但是,我有一个有趣的输出,如下所示:

ABCDEF

我检查了文件,没有多余的空格或字符。但是,当我从字符串后面手动删除时,我什至看不到单个字符。效果很好。我想一定有某种我看不到的“隐藏”字符或线条。

它一直困扰着我,因为我有大量文件需要连接。我无法手动做同样的事情。

任何帮助表示赞赏。

答案1

paste可能是最简单的(更不用说非常高效了)意味着您可以处理这个问题。

printf abc >file1
printf def >file2
paste -sd\\n file[12]

abc
def

paste串行调用时-s,它将依次读取每个命名输入文件以及paste每个文件中 <tab> 或指定分隔符字符串上每一行的输出-d。虽然paste总是以 ewline 结束每个命名 infile 的输出\n,但这里的-d分隔符也被指定为\newline,因此它基本上只是cat将其输入输出,但每个文件总是以\newline 结尾。


正如 Peter 在下面指出的,空文件可能会导致paste发出额外的\newline。如果这是一个问题,实际上可以应用相同的sed方法不是这样做:

: > file0
sed '' file[012]

abc
def

不过现在用这个方法,sed(至少有 GNU )可能有不同的问题。任何sed意愿总是在拉入另一行之前先写出一条\newline,但如果是非常整个串联输入文件系列的最后一行,然后是一些seds(例如 GNU)可能不是在末尾添加一个换行符。例如,对于我的输入文件,定义后面没有换行符。

而如果是一个问题,嗯...

sed '' file[012] | paste -sd\\n

...上述管道可能应该涵盖您的所有基础。

答案2

正如彼得所说,您的第一个文件没有行尾字符。您也许可以用ls -l--- 检查它,如果它恰好是三个字符,那就是它。

如果你想“cat”文件并添加换行符仅有的如果换行符不存在,您可以使用解释的好技巧这里

如果你有这三个文件:

[romano:~/tmp] % ls -l f1 f2 f3
-rw-rw-r-- 1 romano romano 3 Jul 12 14:58 f1
-rw-rw-r-- 1 romano romano 4 Jul 12 15:03 f2
-rw-rw-r-- 1 romano romano 4 Jul 12 15:03 f3
[romano:~/tmp] % cat f1 f2 f3
ABCDEF
GHI

其中f1最后一行没有行尾,而其他行有,你可以这样做:

[romano:~/tmp] % sed -e '$a\' f1 f2 f3
ABC
DEF
GHI

...sed是一个流编辑器,您指示它打印所有未更改的内容,最后一行不添加任何内容 --- 但sed在操作时隐式添加换行符,因此它解决了问题。

请注意,仅使用cat+echo就会添加换行符总是。这样你就有了两个:

[romano:~/tmp] % for i in f?; do cat $i; echo; done;
ABC
DEF

GHI

[romano:~/tmp] %

答案3

看来你file1没有尾随换行符。如果您想连接文件列表。您可以先检查每一项,并cat在需要时检查换行符,如下所示:

# make some sample files
printf "%s\n" abc > file1  
printf "%s"   def > file2  # no trailing newline
printf "%s\n" ghi > file3
printf "%s"   jkl > file4  # no trailing newline

# find files to concatenate and build a sorted array `f[]`
unset f i; 
while IFS= read -r -d $'\0' path; do f[i++]="$path"
done < <(find . -type f -name 'file[0-9]' -print0 | sort -z)

# build the `cat` command
cmd=cat
tmp="$(mktemp)"; echo >$tmp   # a file which contains only `\n`
for file in "${f[@]}"; do
    lasthex=$(tail -c1 $file | hexdump -ve '1/1 "%02x"')
    [[ -z $lasthex ]] && continue     # skip enpty files
    [[ $lasthex == 0a ]] && nl= || nl=" $tmp"
    cmd="$cmd \"$file\"$nl"
done

# execute the `cat` command
eval "$cmd"

连接的结果是:

abc
def
ghi
jkl

生成的命令是:

cat "./file1" "./file2" /tmp/tmp.z7iKccY0T9 "./file3" "./file4" /tmp/tmp.z7iKccY0T9

答案4

您可以在文件中看到特殊字符od -c filename。换行符看起来像\n.如果 Windows 或源代码管理更改了换行符,您将看到\r\nusing od -c,但不会看到任何与 不同的内容cat。您可以用来dos2unix filename修复这些。

有时您会看到 cat 打印出的一系列控制字符,看起来像“-”或其他有效字符。

相关内容