我正在尝试将文本文件转换为制表符分隔的电子表格。我的文本文件如下所示:
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 导入功能中做错了什么:
仅供参考,期望的结果应该是这样的:
答案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 单行命令详解:
如果一行以反斜杠“\”结尾,则将其附加到下一行。
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/ $//'