是否可以使用 Gedit 或命令行来修改文本文件的每四行?

是否可以使用 Gedit 或命令行来修改文本文件的每四行?

我正在尝试将文本文件转换为制表符分隔的电子表格。我的文本文件如下所示:

Dog
Cat
Fish
Lizard
Wolf
Lion
Shark
Gecko
Coyote
Puma
Eel
Iguana

使用 Gedit 或 LibreOffice 中的标准搜索和替换功能,很容易用制表符替换行尾。但如果我只是将回车符替换为制表符,我会得到这样的结果:

Dog   Cat   Fish   Lizard   Wolf   Lion   Shark   Gecko   Coyote   Puma   Eel   Iguana

但我需要做的是让它看起来像这样:

Dog   Cat   Fish   Lizard
Wolf   Lion   Shark   Gecko  
Coyote   Puma   Eel   Iguana

那么,我可以将每个行尾字符替换为制表符吗?除了每四行?

我不知道这种条件迭代是否可以在 Gedit 或 LibreOffice 等程序中使用正则表达式完成,所以也许这需要某种命令行函数?我甚至不清楚最好的入门工具是什么。


更新:

我尝试了以下命令:

sed 'N;N;N;s/\n/\t/g' file > file.tsv

paste - - - - < file > file.tsv

pr -aT -s$'\t' -4 file > file.tsv

xargs -d '\n' -n4 < inputfile.txt

但是当我尝试tsv在 LibreOffice 中打开生成的文件时,列不太正确。我不确定这是否意味着我没有正确执行上述命令,或者我在 LibreOffice 导入功能中做错了什么:

在 Calc 中打开 TSV

仅供参考,期望的结果应该是这样的:

适当的列

答案1

可以使用命令行编辑器,例如sed

sed 'N;N;N;s/\n/\t/g' file > file.tsv

或者,更程序化地,通过添加反斜杠行继续符使用 GNU sed 的地址运算符对要合并的每一行n skip m添加地址,并在其后跟上用于合并连续行的经典单行命令:

sed '0~4! s/$/\t\\/' file | sed -e :a -e '/\\$/N; s/\\\n//; ta'

例如Sed 单行命令详解

  1. 如果一行以反斜杠“\”结尾,则将其附加到下一行。

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    

然而,我认为使用其他标准文本处理实用程序会更容易,例如

paste - - - - < file > file.tsv

(数量-将与列数相对应)或

pr -aT -s$'\t' -4 file > file.tsv

-s$'\t(如果您不介意输出被多个制表符分隔,则可以省略)。


您观察到的奇怪的重新导入行为几乎肯定是因为原始文件具有 Windows 样式的 CRLF 行尾。如果您需要使用 Windows 中的文件,则可以通过各种方式将转换转入命令,例如

tr -d '\r' < file.csv | paste - - - -

或者

sed 'N;N;N;s/\r\n/\t/g' file.csv

前者将删除所有回车符,而后者将在每个新行的末尾保留一个 CR(如果目标最终用户使用的是 Windows,这可能是您想要的)。

答案2

您可以使用xargs始终将四行组合为一行,每行用一个空格分隔:

xargs -d '\n' -n4 < inputfile.txt

-d '\n'将输入分隔符设置为换行符,否则也会在空格处中断。如果每行输入只有一个单词,您甚至可以省略此操作。
-n4将参数编号(每行输出的输入项数)设置为 4。

输出:

Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana

或者,如果您希望使用制表符而不是空格作为分隔符,则可以在之后替换它们。但是,如果您的输入行中有空格,这些空格也会被替换:

xargs -d '\n' -n4 | tr ' ' '\t'

输出(取决于浏览器/终端的标签宽度):

Dog Cat Fish    Lizard
Wolf    Lion    Shark   Gecko
Coyote  Puma    Eel Iguana

答案3

您还可以使用:

awk -v ORS="" '{print $1; print NR%4==0?"\n":"\t"}' file > file.tsv 

两个 awk 内置变量是:

  • ORS输出R记录年代eparator(默认值=newline)。它被添加在每个打印命令的末尾。
  • NR当前号码Row awk 正在处理。

此命令将针对每一行显示第一列(这里仅显示第一列)的内容。然后,它通过测试除以 4 的余数来选择添加换行符或制表符NR

答案4

我的解决方案是使用sed和的组合sed。首先,您可以用一些特殊字符标记每四行,例如>,使用以下解决方案:

在这种情况下,您需要从第 5 行开始,并标记其后的每 4 行。在 GNU 中,sed可以将其作为地址给出5~4。您可以使用以下命令:

sed '5~4s/^/>/' file1 > file2

然后您需要删除换行符,这可以通过循环完成sed

sed ':a;N;s/\n/ /;ba' file2 > file3

有更简单的方法将换行符转换为其他字符,例如tr

tr '\n' ' ' < file2 > file3

无论如何,将两者结合起来

Dog   Cat   Fish   Lizard   >Wolf   Lion   Shark   Gecko   >Coyote   Puma   Eel   Iguana

sed版本留下尾随换行符,而tr版本不留下)

此后,您只需将插入的特殊字符转换为换行符;例如将制表符分隔的文件转换为使用换行符。本例中,改为>换行符:

sed 'y/>/\n/' file3 > outfile

y命令的功能与 相同tr,将一个字符转换为另一个字符,但在这里使用该s命令的效果同样好。使用 时s,您需要g对行 ( sed 's/>/\n/g') 中的每个匹配项进行操作。

您可以使用管道,而不必创建两个中间文件:

$ sed '5~4s/^/>/' file | sed ':a;N;s/\n/ /;ba' | sed 'y/>/\n/'
Dog Cat Fish Lizard 
Wolf Lion Shark Gecko 
Coyote Puma Eel Iguana

如果尾随空格是个问题,您可以添加另一个命令来删除它们:

| sed 's/ $//'

相关内容