编者注::
这个问题有一个困难的编辑历史,因为一个善意但误导的编辑(它引入了无关的,“漂亮的”格式依赖于空格和|
字符来分隔列)暂时混淆了这个问题(自恢复后)。
OP的前提是输入是 tab -delimited,即使它没有直接反映在此处显示的示例输入中。
功能
我有一个包含6列的输入文件,它们以制表符分隔。我想用值'81115'
替换第5列中的所有值,同时保持格式不变。
输入文件:
203 ADD 24 IAC 81216 IT
204 ATT 24 IAC 81216 IT
所需的输出文件:
203 ADD 24 IAC 81115 IT
204 ATT 24 IAC 81115 IT
我的解决方案#1
我使用以下命令:
awk '{$5 = v} 1' v="81115" file > file.NEW
使用上面的命令,第5列将被替换,但列不再以制表符分隔。
输出文件:
203 ADD 24 IAC 81115 IT
204 ATT 24 IAC 81115 IT
我的解决方案#2
要保持我尝试使用以下命令的格式:
awk -v replace="81115" -F '\t' -v OFS='\t' {$5=replace}1' file > file.NEW
OR
awk -F"\t" -v OFS="\t" '{$5=81115}1' file > file.NEW
OR
awk -F '\t' '{$5="81115";}1' OFS='\t' file > file.NEW
以上所有命令都保持格式不变,但最后添加了值为81115
的新列;即第7栏被追加。
输出文件:
203 ADD 24 IAC 81216 IT 81115
204 ATT 24 IAC 81216 IT 81115
有人可以建议替代解决方案或更改上述命令吗?
答案 0 :(得分:1)
对于保留格式的列内更新,您需要使用拆分功能。请注意,只有GNU awk支持带有第四个参数的split函数。
试试这个:
awk '{split($0, a, FS, seps) # split based on FS
a[5]="81115"; # Update the 5th column
for (i=1;i<=NF;i++) # print the data back
printf("%s%s", a[i], seps[i]) # keeping the separators
print ""}' # print a new line
一衬垫:
awk '{split($0, a, FS, seps); a[5]="81115"; for (i=1;i<=NF;i++) printf("%s%s", a[i], seps[i]); print ""}' /tmp/data
答案 1 :(得分:0)
注意:
- 如果必须保留输入和中的完全分隔符字符串,则 GNU awk
,请参阅@Sundeep's helpful answer,或者,对于涵盖所有字段的解决方案,请参阅Jay Rajput's helpful answer
- 此答案尝试诊断OP的问题,并包含一个解决方案,将输入转换为一致的制表符分隔输出。
您的第一次尝试不会保留输出中的标签,因为在没有设置OFS
输出字段分隔符的情况下,Awk将分隔输出字段空间每个。
(通过分配到字段,就像使用$5 = ...
一样,输入行是隐式重建,使用OFS
的值(空格)默认情况下)作为分隔符将(修改的)字段重新组合在一起以形成输出行。)
您的其他尝试看起来都很合理,这表明您的输入文件的结构可能不像您认为的那样。
使用cat -et
验证输入文件中的所有列确实是由每个标签分隔开来的:^I
代表cat -et
输出中的标签。
如果您的输入文件包含 mix 的制表符和空格分隔列和/或某些字段之间有多个制表符,你需要依靠awk
的默认解析来按预期将输入分成字段,即任何非空白空格。<登记/>
然后仅使用OFS
>>将标签用作 on output 的分隔符:
awk -v replace='81115' -v OFS='\t' '{$5=replace}1' file
请注意缺少-F
选项,以便依赖Awk的默认字段拆分行为。
虽然这不一定能保持确切的输入格式,但您将获得始终制表符分隔的输出。
答案 2 :(得分:0)
基于给定样本输入的最简单的解决方案是使用sed
进行简单搜索和替换,假设第5列只有81216
的相同值,并且该值不会出现在1-4中的任何位置柱
$ sed 's/81216/81115/' file
203 ADD 24 IAC 81115 IT
204 ATT 24 IAC 81115 IT
如果必须更换第5列中的任何值,
sed -E 's/^((\S+\s+){4})\S+/\181115/' file
如果无法识别\s
和\S
,请使用
sed -E 's/^(([^[:space:]]+[[:space:]]+){4})[^[:space:]]+/\181115/' file
类似的解决方案可以与GNU awk
具有gensub
函数
awk '{$0 = gensub(/^((\S+\s+){4})\S+/, "\\181115", "1", $0)}1' file
一起使用
awk -v replace='81115' '{$0 = gensub(/^((\S+\s+){4})\S+/, "\\1"replace, "1", $0)}1' file
或者使用变量,
UPDATE table_1
SET col_1 =
CASE WHEN table_1.col_pk IS NULL THEN value1
ELSE value2
END
FROM table_1
LEFT JOIN table_2 ON table_1.col_pk = table_2.col_pk
以上所有解决方案都保留了输入文件空间格式