如何对文件夹中的所有文件应用'awk'?

时间:2015-07-23 22:45:26

标签: bash unix awk

我是新手,请原谅我的无知。我使用awk从文件中提取标记值。以下代码适用于单次执行

awk -F"<NAME>|</NAME>" '{print $2; exit;}' file.txt

但我不知道如何为文件夹中的所有文件运行它。 文件样本如下

<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>

2 个答案:

答案 0 :(得分:0)

    #!/bin/bash

    STRING=ABC
    DATE=$(date +%Y/%m/%d | tr '/' '-')

    changedate(){
    for a in $(ls /root/Working/awk/*)
    do
    for b in $(awk -F"<NAME>|</NAME>" '{print $2;}'  "$a")
    do
    if [ "$b" == "$STRING" ]; then
    for c in $(awk -F"<DATE>|</DATE>" '{print $2;}' "$a")
    do
    sed "s/$c/$DATE/g" "$a";
    done
    else
    echo "Strings are not a match";
    fi
    done
    done
    }

changedate

当你运行它时 -

root@revolt:~# cat /root/Working/awk/*
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>DEF</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>GHI</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>JKL</NAME><DATE>2015-12-11</DATE></BODY>

代码中的字符串设置为ABC

root@revolt:~# ./ANSWER
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-07-24</DATE></BODY>
Strings are not a match
Strings are not a match
Strings are not a match

代码中的字符串设置为DEF

root@revolt:~# ./ANSWER
Strings are not a match
<HEADER><H1></H1></HEADER><BODY><NAME>DEF</NAME><DATE>2015-07-24</DATE></BODY>
Strings are not a match
Strings are not a match

好的。所以在这里你可以设置STRING = ABC或任何你想要的字符串。您还可以将其设置为=您要检查的字符串列表。 日期变量以与字符串相同的格式(Y / m / d)回显日期。然后,tr命令用连字符替换正斜杠的所有实例。

首先我们要创建一个名为“changedate”的函数。在这个函数中,我们将嵌套一些for循环来做不同的事情。第一个for循环将ls /root/Working/awk/*设置为变量a。这意味着对于/ root / Working / awk /中的文件/目录的每个实例,请执行以下操作。 下一个for循环是检查每个实例,在Name标签之间抓取并打印它。请注意,我们仍然使用$ a作为文件,因为这将是每个文件的文件路径。然后我们将有一个if语句来检查你的字符串。如果是,则执行另一个for循环,替换文件a中的日期。如果不是,则回显Strings are not a match

最后,我们称之为“changeate”函数,它基本上运行上面的整个循环序列。

答案 1 :(得分:0)

回答一下你在多个问题上运行awk的问题 文件,想象我们有这些文件:

$ cat file1.txt
<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>

$ cat file2.txt
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-12-11</DATE></BODY>

$ cat file3.txt
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>

您可以做的一件事就是为awk提供多个文件,就像几乎所有命令一样(例如ls *.txt):

$ awk -F"<NAME>|</NAME>" '{print $2}' *.txt
XYZ
ABC
123

Awk只是依次读取每个文件中的行。正如评论中所提到的, 小心exit因为它会在第一场比赛后停止一起处理::

$ awk -F"<NAME>|</NAME>" '{print $2; exit}' *.txt
XYZ

但是,如果出于效率或其他原因,您想要停止 处理当前文件并立即前进到下一个文件, 你只能使用gawk nextfile

$ # GAWK ONLY!
$ gawk -F"<NAME>|</NAME>" '{print $2; nextfile}' *.txt
XYZ
ABC
123

有时,如果不知道,多个文件的结果就无用了 哪个行来自哪个文件。为此,您可以使用内置的FILENAME 变量:

$ awk -F"<NAME>|</NAME>" '{print FILENAME, $2}' *.txt
file1.txt XYZ
file2.txt ABC
file3.txt 123

当您想要修改正在使用的文件时,事情会变得棘手 上。想象一下,您想将名称转换为小写:

$ awk -F"<NAME>|</NAME>" '{print tolower($2)}' *.txt
xyz
abc
123

使用传统的awk,通常的模式是保存到临时文件和副本 将temp文件恢复原状(显然你要小心 这,保留orignals的副本!)

$ cat file1.txt
<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>

$ awk -F"<NAME>|</NAME>" '{ sub($2,tolower($2)); print }' file1.txt > tmp && mv tmp file1.txt

$ cat file1.txt
<HEADER><H1></H1></HEADER><BODY><NAME>xyz</NAME><DATE>2015-12-11</DATE></BODY>

要在多个文件上使用此样式,可能更容易退回 shell并在单个文件的循环中运行awk:

$ cat file1.txt file2.txt file3.txt
<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>

$ for f in file*.txt; do
>   awk -F"<NAME>|</NAME>" '{ sub($2,tolower($2)); print }' $f > tmp && mv tmp $f
> done

$ cat file1.txt file2.txt file3.txt
<HEADER><H1></H1></HEADER><BODY><NAME>xyz</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>abc</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>

最后,使用gawk,你可以选择就地编辑(很像sed -i):

$ cat file1.txt file2.txt file3.txt
<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>

$ # GAWK ONLY!
$ gawk -v INPLACE_SUFFIX=.sav  -i inplace -F"<NAME>|</NAME>" '{ sub($2,tolower($2)); print }' *.txt

$ cat file1.txt file2.txt file3.txt
<HEADER><H1></H1></HEADER><BODY><NAME>xyz</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>abc</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>

推荐的INPLACE_SUFFIX变量告诉gawk进行备份 具有该扩展名的每个文件:

$ cat file1.txt.sav file2.txt.sav file3.txt.sav
<HEADER><H1></H1></HEADER><BODY><NAME>XYZ</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>ABC</NAME><DATE>2015-12-11</DATE></BODY>
<HEADER><H1></H1></HEADER><BODY><NAME>123</NAME><DATE>2015-12-11</DATE></BODY>