我正在尝试将文本插入到任何空白列中。该文件是制表符分隔的,我试图将文本插入到任何空白列中。例如
Column1 Column2 Column3
string1 decs1 1234
desc1 1255
string3 3443
string4 desc1 1
string5 435
我试图仅将文本 NULL 插入空白的列 1 或 2 中。所以它看起来像这样。 (如果第 2 列为空,则第 1 列和第 3 列之间有一个双制表符)
column1 column2 column3
string1 decs1 1234
null desc1 1255
string3 null 3443
string4 desc1 1
string5 null 435
我尝试过使用awk
,但我的测试会将 NULL 文本插入到所有列 2 中,但如果那里有空白条目,则会将第三列截断到列 2 中。
awk '{sub("$", "NULL", $2)}; 1' file.txt > file2.txt
结果是这样的
column1 column2 column3
string1 desc1NULL 1234
string2 desc1NULL 1255
string3 3443NULL
string4 descNULL 1
string4 435NULL
我显然使用了不正确的语法,但不知道如何纠正它。
谢谢
答案1
我建议这样做sed
:
sed -E -e :1 -e 's/(^|\t)(\t|$)/\1null\2/;t1' yourfile
(为了可移植性,请使用实际的 TAB 字符而不是\t
,但这可能无法在浏览器复制/粘贴中幸存。)
如何检测空字段?要么是
- 行首的制表符 (
^\t
) 或 - 两个选项卡之间没有任何内容 (
\t\t
) 或 - 行尾有一个制表符 (
\t$
)
在所有这些情况下,s
请在两个匹配之间替换您的模式。
如果有两个接一个的空字段,我们需要循环,因此如果替换了某些内容,则t1
跳转到标记。:1
答案2
awk -F'\t' -v OFS='\t' '$1==""{ $1="NUll" } $2==""{ $2="NUll" }1' infile
和sub("$", "NULL", $2)
$
,您正在调用 sub() 函数以将column#2 的字符串结尾替换$2
为“NULL”字符串。此外,仅当这些列为空时,才用“NULL”替换这些列,使用 sub() 的方式,您可以执行以下操作:
awk -F'\t' -v OFS='\t' '
$1==""{ sub(/.*/, "NULL", $1) }
$2==""{ sub(/.*/, "NULL", $2) }
$3=="" { "......" }
# etc ...
1' infile
或者可能:
awk -F'\t' -v OFS='\t' '
{ sub(/.*/, ($1==""?"NULL":$1), $1) }
{ sub(/.*/, ($2==""?"NULL":$2), $2) }
# continue ...
1' infile
...但这与之前的第一个命令相比有点糟糕;或者您可以使用以下变体,以防替换作业不仅限于两列,而且考虑到它在氮列。
awk -F'\t' -v OFS='\t' -v N=2 '{
while(colNr++<N){
$colNr=($colNr==""?"NULL":$colNr)
}
colNr=0
}1' infile
答案3
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ awk 'BEGIN{FS=OFS="\t"} {for (i=1; i<=NF; i++) if ($i=="") $i="null"} 1' file
Column1 Column2 Column3
string1 decs1 1234
null desc1 1255
string3 null 3443
string4 desc1 1
string5 null 435
使用sub()
s 将是:
$ awk '{ while(sub(/\t\t/,"\tnull\t")); sub(/^\t/,"null\t"); sub(/\t$/,"\tnull")}1' file
Column1 Column2 Column3
string1 decs1 1234
null desc1 1255
string3 null 3443
string4 desc1 1
string5 null 435
答案4
使用 csvkit 工具创建一个中间 JSON 文档,我们通过用字符串替换所有不存在的值来修改该文档NULL
,然后将修改后的 JSON 文档转换回制表符分隔的 CSV:
csvjson -t file |
jq '.[] |= map_values(. // "NULL")' |
in2csv --blanks -f json | csvformat -T
在这里,我们首先使用csvjson -t
解析来自名为 的文件的制表符分隔输入file
,输出 JSON。然后,我们调用jq
以修改生成的文档,用字符串替换所有空值NULL
。该in2csv
调用读取 JSON 文档并生成 CSV,以--blanks
避免NULL
用空值替换字符串。最后,使用 重新格式化 CSV 数据以制表符分隔csvformat -T
。
同样的事情,但允许jq
处理单个行的流,而不必读取整个数据集的数组。然后以相同的方式将数据流式传输到in2csv
.
csvjson --stream -t file |
jq -c 'map_values(. // "NULL")' |
in2csv -f ndjson --blanks | csvformat -T