如何从awk的输入FILENAME变量中删除路径-基本名称是否可用?

时间:2019-03-13 18:47:26

标签: bash awk

以下命令

gawk '{print $0, FILENAME}' input.txt > result.txt

其中input.txt为:

FIXED3 LENGTH7      FILE FORMAT     00001
FIXED2 LENGTH8      FILE FORMAT     00002
FIXED2 LENGTH20     FILE FORMAT     00003
FIXED1 LENGTH20     FILE FORMAT     00004

产生以下所需结果:

FIXED3 LENGTH7      FILE FORMAT     00001 input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 input.txt

但是,如果使用如下所示的文件路径:

gawk '{print $0, FILENAME}' /cygdrive/c/dev/data/input.txt > result.txt

然后,附加到每行的FILENAME也包含路径。这是我要纠正的,我希望得到与上述第一种情况相同的结果。

FIXED3 LENGTH7      FILE FORMAT     00001 /cygdrive/c/dev/data/input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 /cygdrive/c/dev/data/input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 /cygdrive/c/dev/data/input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 /cygdrive/c/dev/data/input.txt

5 个答案:

答案 0 :(得分:3)

这是一种方式:

$ gawk '{f=FILENAME; sub(/^.*\//,"",f); print $0, f}' ../here/file
FIXED3 LENGTH7      FILE FORMAT     00001 file
FIXED2 LENGTH8      FILE FORMAT     00002 file
FIXED2 LENGTH20     FILE FORMAT     00003 file
FIXED1 LENGTH20     FILE FORMAT     00004 file

解释:

$ gawk '{
    f=FILENAME          # copy the filename to f
    sub(/^.*\//,"",f)   # process f instead, removeall from beginning to last /
    print $0, f         # etc. etc.
}' ../here/file

或者因为您确实提到了gawk

$ gawk '{print $0, gensub(/^.*\//,"",1,FILENAME)}' ../here/file

答案 1 :(得分:3)

FILENAME/拆分为一个数组,并输出数组的最后一个元素:

awk '{n=split(FILENAME,array,"/"); print $0, array[n]}' /cygdrive/c/dev/data/input.txt

答案 2 :(得分:1)

对效率和简洁性进行一些调整:

gawk 'FNR==1{f=gensub(".*/","",1,FILENAME)} $(NF+1)=f'

通过在第一行执行该部分,仅从每个文件中提取一次filename(此处为f)。 并且由于FILENAME不会为空,因此只需将其附加到该行中,即可隐含{print $0}

但是,如果不是一个空格,那将改变输出分隔符。
如果不是您想要的,请使用下面的一个:

gawk 'FNR==1{f=gensub(".*/","",1,FILENAME)}{print $0 OFS f}'

答案 3 :(得分:0)

能否请您尝试以下。它只会在第一行运行以获取确切的Input_file名称,而不会在文件的每一行运行。

awk 'FNR==1{if(FILENAME~/\//){sub(/.*\//,"",FILENAME)}} {print $0,FILENAME}' Input_file

这种方法的可能好处:

1-不在每行上生成编辑的文件名,获取本身在第一行,而在所有其他行中仅打印prinintg。

2-没有创建数组/内存占位符,因此在大型文件上也应该是FAST。

3-因为我只是打印它,而不用它的文件名值创建任何附加列,这也可以节省这段代码的运行时间。



编辑: 也有另一种想法,您可以简单地导航到存在Input_file的新目录,并可以返回代码/一个内衬本身,例如以下示例。恕我直言,我希望这将是这里提到的所有其他解决方案中最快的(因为我们在这里没有进行任何数据操作,而且我们也使用了您以前使用过的相同命令:))

cd  /cygdrive/c/dev/data/ && awk '{print $0,FILENAME}' input.txt && cd -

此命令的特殊之处在于它将返回到您正在运行代码的原始目录,因此您永远不会感觉自己导航到任何地方:)

答案 4 :(得分:0)

另一个awk使用/作为分隔符

gawk -F"/"  ' { printf("%s ",$0) ; $0=FILENAME } { print $NF } ' /home/full/path/input.txt

使用您给定的输入

$ cat /cygdrive/c/dev/data/input.txt
FIXED3 LENGTH7      FILE FORMAT     00001
FIXED2 LENGTH8      FILE FORMAT     00002
FIXED2 LENGTH20     FILE FORMAT     00003
FIXED1 LENGTH20     FILE FORMAT     00004

$ gawk -F"/"  ' { printf("%s ",$0) ; $0=FILENAME } { print $NF } ' /cygdrive/c/dev/data/input.txt
FIXED3 LENGTH7      FILE FORMAT     00001 input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 input.txt

$