【发布时间】:2019-06-05 17:17:20
【问题描述】:
我有一个格式如下的文件(data.rdb):
date star jdb texp
2013-11-22 epsInd 2400000.23551544 100.
2013-11-22 epsInd 2400000.23551544 100.
2013-11-22 epsInd 2400000.23551544 100.
2013-11-22 HD217987 2400000.23551544 900.
2013-11-22 TOI-134 2400000.23551544 900.
2013-11-22 tauCet 2400000.23551544 60.
2013-11-22 BD+01316 2400000.23551544 300.
2013-11-22 BD+01316 2400000.23551544 300.
2013-11-22 BD+01316 2400000.23551544 300.
2013-11-22 BD+01316 2400000.23551544 300.
一些属性:
- 所有列都用制表符分隔
- 列的宽度不同
- 单元格的长度可能不同
- 该文件的列数将比显示的多得多,并且有数百行
- 列名可以是任何单词,不能有制表符、空格或特殊字符
如何将标题为 jdb 的列移动为第一列?
一些限制:
- 这将应用于多个文件,
jdb列不会总是出现在同一位置 - 理想情况下,其余列的顺序不应改变
-
jdb将始终是最后的第一列。
谢谢!
更新
这是我目前使用的awk 块:
BEGIN {
numCols = split(column_list,cols)
OFS="\t"
}
{ sub(/\r$/,"") }
NR==1 {
for (fldNr=1; fldNr<=NF; fldNr++) {
f[$fldNr] = fldNr
}
}
{
for (colNr=1; colNr<=numCols; colNr++) {
colName = cols[colNr]
colVal = (colNr=1 ? $(f["jdb"]): (colNr <= $(f["jdb"] ?
$(f[colName] -1) : $(f[colName]))))
printf "%s%s", colVal, (colNr<numCols ? OFS : ORS)
}
}
但它没有给我任何输出......我(认为我)做了什么:
为每个列标题值分配一个数字
-
遍历一个范围
2.1 if iterator = 0 -> 打印列
jdb2.2 if iterator 打印列号
iterator - 12.3 if iterator > jdb的列号->打印列号
iterator
(这是我在https://stackoverflow.com/questions/56132249/extract-columns-from-tab-separated-file)提出的问题的延续@
结束结果
最后我最终使用了@Ed Morton 的解决方案:
$ cat move_to_first.awk
BEGIN { FS=OFS="\t" }
NR==1 {
cols[++numCols] = tgt
for (fldNr=1; fldNr<=NF; fldNr++) {
f[$fldNr] = fldNr
if ($fldNr != tgt) {
cols[++numCols] = $fldNr
}
}
}
{
for (colNr=1; colNr<=numCols; colNr++) {
colName = cols[colNr]
printf "%s%s", $(f[colName]), (colNr<numCols ? OFS : ORS)
}
}
出于好奇,要将列移动到最后一个位置,上面的代码只需要以下修改:
$ cat move_to_last.awk
BEGIN {
FS=OFS="\t"
}
NR==1 {
for (fldNr=1; fldNr<=NF; fldNr++) {
f[$fldNr] = fldNr
if ($fldNr != target) {
cols[++numCols] = $fldNr
}
}
cols[++numCols] = target
}
{
for (colNr=1; colNr<=numCols; colNr++) {
colName = cols[colNr]
printf "%s%s", $(f[colName]), (colNr<numCols ? OFS : ORS)
}
}
【问题讨论】:
-
也许考虑安装专门的实用程序来处理类似 csv 的文件,而不是用 bash 和 awk 重新发明轮子,比如 csvkit
-
@EdMorton:我的第一次尝试是两次使用您之前回答中建议的方法,一次选择
jdb列,第二次选择所有其他列。然后我会连接。但这很难看,所以我仍在寻找更优雅的解决方案。我要做的是选择列jdb,将其索引存储在变量中,然后在打印时重新排序... -
=是赋值,==是比较。请参阅colNr=1作为脚本中三元组中的条件。