4

我想使用 awk 替换文件列表中的文本。我认为这是适合这项工作的工具,因为:

“在处理文本文件时,有几种任务会重复发生。您可能想要提取某些行并丢弃其余的行。或者您可能需要在某些模式出现的地方进行更改,但不理会文件的其余部分。”

http://www.gnu.org/software/gawk/manual/gawk.html

这正是我想做的。

awk 读取 filelist.txt(这是一个包含要修改的每个文件的路径的文件)匹配 pattern.txt(这是一个包含 javascript 的文件,并且是我希望从 filelist 中包含的所有 htm 文件中剔除的文件。文本)

我使用 filelist.txt 的原因是有几个文件要删除 javascript,它们位于多个位置。

我想使用 pattern.txt 的原因是 javascript 包含各种各样的东西,比如空格、特殊字符等。

如果我尝试为 awk 提供整个 javascript,我将不得不一个接一个地转义其中包含的所有特殊字符,这将非常耗时。(而且可能行不通,而且非常复杂!)

如果我尝试只放置 javascript 的开头和结尾,例如:

awk '/<\/SCRIPT>/{p=1;print}/<\/script>/{p=0}!p'    

我冒着删除所有嵌入式 javascript 实例的风险,而不仅仅是想要的。

我想用 awk 做的事情可行吗?

这取决于我的信念,即为它提供文件将使它将文件的全部内容解释为模式,而不是在遇到的第一个符号上窒息。

4

3 回答 3

2

我不确定这awk是适合这项工作的工具。它通常打印到标准输出,而您似乎想要覆盖原始文件。

为此,Perl 有一个内置机制:perl -i.bak将覆盖文件,为每个文件创建一个带有可选后缀的备份副本.bak;如果省略后缀,则不会得到备份。

如果我正确理解了您的模式匹配方案,那么您需要从数据文件中删除一行相当多的 JavaScript 代码。但是,这些文件很可能包含 JavaScript 的其他片段,因此您不能简单地查找具有简单开头的行。同样,我认为 Perl 会更好。您可以将pattern.txt文件读入一个变量,然后从该变量创建一个带有适当修饰的正则表达式,以抑制元字符的所有特殊含义(\Q并且\E;您的 JavaScript 会包含\E吗?)。Perl 允许您将整个文件 slurp 到内存中,然后将多行正则表达式应用于整个文件——这些属性可能在这段代码中很有用。我不确定是否(如何)啜饮与-i选项; 那将不得不检查。

这些特殊技巧中没有一个是现成的awk(甚至不是gawk),这让我认为这awk可能不是这项工作的最佳工具。我使用 Perl 是因为我很久以前就学会了它。我希望 Python 或 Ruby 或任何其他较新的脚本语言也可能能够管理它。


Perl 演示

slurper.pl

#!/usr/bin/perl -i.bak
use strict;
use warnings;

my $pattfile = shift;
my $pattern;
{
    open my $ph, '<', $pattfile or die "Failed to open $pattfile: $!";
    local $/;
    $pattern = <$ph>;
}

# chomp removes what's in $/ - don't chomp while $/ is undef!
chomp $pattern;

my $regex = qr{ \Q$pattern\E }mx;

# Slurp each file in turn
local $/;
while (<>)
{
    s/$regex//g;
    print;
}

磷:

X ok X ok

X:

abcXdef
X ok X ok

是:

abcXdef
X ok X ok
no x's here

z:

no x's here either
abcXdef
X ok X ok

执行

$ perl slurper.pl p x y z
$ ls ? ?.bak
p     x     x.bak y     y.bak z     z.bak
$

磷:

X ok X ok

X:

abcXdef

是:

abcXdef

no x's here

z:

no x's here either
abcXdef
于 2012-04-13T10:05:17.933 回答
0

TXR执行整个文件模式匹配。在 TXR 模式中,您只需转义一个字符@。这有一个特殊的含义,所以要编码一个文字@,只需写@@。(多一个字符有特殊含义,实际上:一个空格(即不与另一个空格相邻)。这被视为正则表达式“匹配一个或多个空格”,这是您经常想要的一点松弛。

@(collect)
@  (cases)
text you want to
change to something
else
@    (output)
multi line
replacement
@    (end)
@  (or)
@line
@    (output)
@line
@    (end)
@  (end)
@(end)

该语言不太适合文本过滤,您只需保持大量文本相同,并在几个地方替换,但它会通过一点编码来完成这项工作。在这里,我们有一个面向行的@(collect)情况,其中包含两种模式匹配情况:一个多行事物,以及一个仅抓取一行的后备情况。如果多行的东西匹配,输入会自动前进过去;这就像标记化,除了超过行而不是字符。

您可以将尾随上下文(未使用)与 匹配@(trailer),例如

text you want to
change to something
else
@(trailer)
which must be followed by
this part that is not
consumed; and the match
continues within this part

您要更改为其他内容的文本可以分解为位于单独文件中的模式函数:

@(define matchtext)
text you want to
change to something
else
@(end)
@(define replacement)
@  (output)
multi line
replacement
@  (end)    
@(end)

然后只是:

@(load "text-and-replacement")
@(collect)
@  (cases)
@    (matchtext)
@    (replacement)
@  (or)
@line
@    (output)
@line
@    (end)
@  (end)
@(end)
于 2012-04-13T20:19:24.790 回答
0

好吧,我在命令行上失败了,但我成功地完成了我的任务。

我使用了一个名为 easy find found @ http://www.devon-technologies.com的程序,并使用变量 createDocumentFragm 来查找所有已更改的文档。

然后我使用 Search&Replace found @ http://searchreplaceapp.com并粘贴了整个 JavaScript,不包括开始和结束处的脚本标签,第二遍手动取消隐藏文件,然后手动删除了 12 个 JavaScript 的 glob导致 find&replace 崩溃的 1050。我不得不手动编辑这些。

所以...在命令行上失败,传递 lame-o gui 工具。

非常感谢大家的回答。

:(

(我认为需要学习 Perl,这是一项值得的努力,因为我怀疑在不久的将来我会遇到类似的实例。)

于 2012-04-13T17:18:48.280 回答