将字符串插入空白列

将字符串插入空白列

我正在尝试将文本插入到任何空白列中。该文件是制表符分隔的,我试图将文本插入到任何空白列中。例如

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

相关内容