【问题标题】:Can I use a file as a pattern for awk to remove from a list of other files?我可以使用文件作为 awk 从其他文件列表中删除的模式吗?
【发布时间】:2012-04-25 12:27:05
【问题描述】:

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

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

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

这正是我想做的。

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

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

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

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

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

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

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

我试图用 awk 做的事情可行吗?

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

【问题讨论】:

  • 好问题,您可以通过添加示例数据来改进它,并从该数据中采样所需的输出。祝你好运。
  • 如果您的网站被黑客入侵,唯一合理的补救措施是从版本控制回滚到已知良好的备份或快照。你已经在使用两者是有原因的,你知道...

标签: bash shell scripting awk


【解决方案1】:

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

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

如果我正确理解了您的模式匹配方案,那么您需要从数据文件中删除一行相当多的 JavaScript 代码。但是,这些文件很可能包含 JavaScript 的其他片段,因此您不能简单地查找具有简单开头的行。同样,我认为 Perl 会更好。您可以将pattern.txt 文件读入一个变量,然后从该变量创建一个带有适当修饰的正则表达式,以抑制元字符的所有特殊含义(\Q and \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;
}

之前

p:

X ok X ok

x:

abcXdef
X ok X ok

y:

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
$

之后

p:

X ok X ok

x:

abcXdef

y:

abcXdef

no x's here

z:

no x's here either
abcXdef

【讨论】:

    【解决方案2】:

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

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

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

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

    非常感谢大家的回答。

    :(

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

    【讨论】:

      【解决方案3】:

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-18
        • 2010-11-12
        • 2023-01-26
        • 2011-11-13
        • 1970-01-01
        • 2020-02-25
        • 2015-04-04
        • 1970-01-01
        相关资源
        最近更新 更多