所以我有一个TSV
看起来像这样的文件:
Hello world how are you
1 2 3 4 5
6 7 8 9 0
(在上面的手写玩具示例中,我用一个空格分隔了每一行中的所有内容。)
我的目标是获取包含“how”和“are”的列作为第一行值。因此,输出将如下所示:
how are
3 4
8 9
问题是我不知道这些模式(即“如何”和“是”)将出现在哪一列。因此,例如,该TSV
文件实际上可以这样排列:
Hello how world are you
1 3 2 4 5
6 8 7 9 0
我知道如何处理这个问题,例如python
(只需转置文件,然后选择我想要的行),但我想在 shell 中执行此操作(出于原因)。问题是,我不知道该怎么做。我知道使用命令行实用程序也可以进行转置(例如,参见这里)但如果可以的话,我想避免使用那些庞大的代码。我最初的、头脑简单的解决方案只是grep
“如何”和“是”,但这显然返回了整个文件,这就是我一直陷入困境的地方。
任何帮助或指示将不胜感激!
编辑:我必须提到,我没有在这台机器上安装任何新工具的权限。我也很不确定它实际上带有什么。如果有帮助的话,这是Scientific Linux 7.3 (Nitrogen)
。
答案1
使用csvtool
1:
csvtool -t ' ' -u ' ' namedcol how,are file
-t Input separator char.
-u Output separator char.
namedcol <names>
Assuming the first row of the CSV file is a list of column headings,
this returned the column(s) with the named headings.
^sudo apt install csvtool
答案2
通过awk
您可以检查第一行是否有匹配的关键字,记下列号,然后打印相应的值:
#first line -> Select columns based on keyword
NR==1 {
for (i = 1; i <= NF; i++) {
if ( $i == "how" ) {col_how=i}
if ( $i == "are" ) {col_are=i}
}
}
#print selected columns including header line
NR>=1 {
print $col_how, $col_are
}
另存为egscript.awk
并执行
awk -f script.awk datafile
编辑:
您的转置和 ing 想法也grep
可以轻松实现:
datamash transpose <datafile | grep 'how\|are' | datamash transpose
用于-t ' '
将空格定义为分隔符。然而,对于很长的文件,这可能会遇到 RAM 限制。但是,大多数机器上可能未按标准安装。
答案3
$ cat tst.awk
BEGIN {
cols = (cols == "" ? "how are" : cols)
nf = split(cols,tgts)
FS = OFS = "\t"
}
NR==1 {
for (i=1; i<=NF; i++) {
f[$i] = i
}
}
{
for (i=1; i<=nf; i++) {
printf "%s%s", $(f[tgts[i]]), (i<nf ? OFS : ORS)
}
}
。
$ awk -f tst.awk file
how are
3 4
8 9
。
$ awk -v cols='are world you Hello' -f tst.awk file
are world you Hello
4 2 5 1
9 7 0 6