代码之家  ›  专栏  ›  技术社区  ›  GeekTantra

Awk替换单引号

  •  4
  • GeekTantra  · 技术社区  · 16 年前

    我要全部替换 include('./ include(' . 我尝试使用awk如下:

    awk '{gsub("include\('"'"'./", "include\('"'"'", $0); print > FILENAME}' *.php
    

    它让我犯了这个错误。

    awk: (FILENAME=xyz.php FNR=1) fatal: Unmatched ( or \(: /include('.//
    

    任何帮助都将不胜感激。

    4 回复  |  直到 16 年前
        1
  •  12
  •   ghostdog74    16 年前

    \047 )和正斜杠( \057

    $ cat file
    include('./
    $ awk '{gsub(/include\(\047\.\057/ , "include(\047" ) }1' file
    include('
    
        2
  •  2
  •   Jonathan Leffler    16 年前

    这是可行的(没有“打印”上的I/O重定向):

    awk '{gsub(/include\('"'"'.\//, "include\('"'"'", $0); print }' # Wrong
    awk '{gsub(/include\('"'"'.\//, "include('"'"'", $0); print }'  # Right
    

    它映射此输入:

    include('./abc')
    include('x/abc')
    

    include('abc')
    include('abc')
    

    根据经验,正则表达式似乎必须在斜线内;替换字符串必须是常规字符串。你需要绘制 . '收件人' \. “停止第二次替换。

    我对这个解释不太满意。MacOS X上“awk”的手册页上说:

    /re/是一个常量正则表达式;任何字符串(常量或变量)都可以用作正则表达式,但模式中独立正则表达式的位置除外。

    所以,理论上,你使用的弦形式应该是可行的。从经验上看,没有;我得到的错误信息与你的代码基本相同。你的shell引用是正确的,这是非常重要的。

    有时Perl可能更容易(因为可以选择任意分隔符来标记regex边界):

    perl -pe "s%include\('\./%include('%g"
    
        3
  •  0
  •   ant    16 年前

    awk '{gsub("include(\'"'"'./", "include\('"'"'", $0); print > FILENAME}' *.php
    

    你放错反斜杠了

    或者这个:

     awk '{gsub("include(\'./", "include(\'", $0); print > FILENAME}' *.php
    

    这个怎么样?

    awk '{gsub("include(\47./", "include(\47", $0); print > FILENAME}' *.php
    

    awk '{gsub("include('./", "include('", $0); print > FILENAME}' *.php
    
        4
  •  0
  •   vladr    16 年前

    你不需要使用 awk 而且,在读取文件时以这种方式写入文件会导致数据丢失或损坏 ,尽量不要这样做。

    for file in *.php ; do
    # or, to do this to all php files recursively:
    # find . -name '*.php' | while read file ; do
      # make backup copy; do not overwrite backup if backup already exists
      test -f $file.orig || cp -p $file $file.orig
      # awk '{... print > NEWFILE}' NEWFILE="$file" "$file.orig"
      sed -e "s:include('\./:include(':g" "$file.orig" >"$file"
    done
    

    只是澄清一下数据丢失的方面:什么时候 啊 sed )开始处理一个文件,你让他们读取第一行,他们实际上会执行缓冲读取,也就是说,为了获得更好的性能(通过减少磁盘I/O),他们将从文件系统(简化为“从磁盘”)中读取与内部读取缓冲区(例如4-65KB)一样大的数据块。假设您正在处理的文件大于缓冲区大小。进一步的读取将继续从缓冲区来,直到缓冲区耗尽,此时第二个数据块将从磁盘加载到缓冲区等。

    但是,就在您读取第一行之后,即在第一个数据块从磁盘读入缓冲区之后,您的 脚本打开 FILENAME ,输入文件本身,用于写入 ,即。 . 此时,原始文件的所有剩余部分都是 的记忆。 Awk 将愉快地继续从内存缓冲区中逐行读取并产生输出,直到缓冲区耗尽为止,此时 可能会停下来给你留下一个4-65k的文件。

    作为一个补充,如果你真的使用awk来扩展(例如。 print "PREFIX: " $0 ),不收缩( gsub(/.../, "") 以及不断增长的文件。:)