首页 > 解决方案 > Linux按行数溢出的文本文件将换行符保留在适当的位置

问题描述

我是 linux 新手(不是我自己的服务器),我想通过从第三方应用程序调用 bash 脚本来拆分一些 windows txt 文件:

到目前为止,我有两种工作方式:

split -l 5000 LargeFile.txt SmallFile

for file in LargeFile.*
do
    mv "$file" "$file.txt"
done

awk '{filename = "wrd." int((NR-1)/5000) ".txt"; print >> filename}' LargeFile.txt

但两者都给了我 txt 文件的结果:

线1线2线3线4

我发现了一些关于像 $ (LargeFile.txt) 这样放置 LargeFile.txt 的主题,但它对我不起作用。(我还找到了一个让 split 命令直接生成 txt 文件的开关,但这也不起作用)

我希望有人可以帮助我解决这个问题。

标签: linuxsplitnewline

解决方案


说明:线路终结器

正如对此问题的各种答案所解释的那样,标准行终止符在操作系统之间有所不同:

  • Linux 使用LF(换行, 0x0a)
  • Windows 使用CRLF(回车和换行0x0d 0x0a
  • Mac, pre OS X used CR(回车CR)

要解决您的问题,重要的是要弄清楚您的 LargeFile.txt 使用哪些行终止符。最简单的方法是file命令:

file LargeFile.txt

输出将指示行终止符是否为CRCRLF,否则仅声明它是一个 ASCII 文件。

由于LFCRLF行终止符将在 Linux 中被正确识别,并且行不应出现合并在一起(无论您使用哪种方式查看文件),除非您专门配置编辑器以便它们这样做,我将假设您的文件具有CR行终止符。

您的问题的示例解决方案(假设CR行终止符)

如果您想在 shell 中使用 shell 命令拆分文件,您可能会面临这样的问题,即cat, split,awk等一开始就无法识别行尾。如果您的文件非常大,这可能还会导致内存问题 (?)。

因此,处理此问题的最佳方法可能是首先翻译行终止符(使用tr命令),以便在 Linux 中理解它们(即 to LF),然后在将行终止符翻译回来之前应用您的splitawk代码(如果您认为需要去做这个)。

cat LargeFile.txt | tr "\r" "\n" > temporary_file.txt
split -l 5000 temporary_file.txt SmallFile
rm temporary_file.txt
for file in `ls SmallFile*`; do filex=$file.txt; cat $file | tr "\n" "\r" > $filex; rm $file; done

请注意,最后一行实际上是一个 for 循环:

for file in `ls SmallFile*` 
do 
    filex=$file.txt 
    cat $file | tr "\n" "\r" > $filex
    rm $file
done

此循环将再次用于tr恢复CR行终止符,并另外为生成的文件提供txt文件名结尾。

一些备注

当然,如果您想保留LF行终止符,则不应执行此行。

最后,如果您发现您有不同类型的行终止符,您可能需要调整tr第一行中的命令。

trsplit(以及catrm)都是 GNU coreutils 的一部分,应该安装在您的系统上,除非您处于非常非典型的环境中(可能是初始 RAM 磁盘的救援外壳)。这个file命令也一样(通常应该可用)。


推荐阅读