awk取代单引号

时间:2010-02-25 09:29:06

标签: unix shell awk

我想用include('./替换一组文件中的所有include('。我试图使用awk如下:

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

它抛出了这个错误。

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

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:12)

@OP,你可以尝试使用八进制代码作为单引号(\047)和正斜杠(\057),例如

$ cat file
include('./
$ awk '{gsub(/include\(\047\.\057/ , "include(\047" ) }1' file
include('

答案 1 :(得分:2)

这有效(没有“打印”上的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可能更容易(因为您可以选择任意分隔符来标记正则表达式边界):

perl -pe "s%include\('\./%include('%g"

答案 2 :(得分:0)

试试这个:

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

答案 3 :(得分:0)

如果你想要做的就是这个,你不需要使用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

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

但是,在您读完第一行之后,即在将第一个数据块从磁盘读入缓冲区之后,您的awk脚本将打开FILENAME,输入文件本身用于写入< strong> with truncation ,即磁盘上文件的大小重置为0 。此时,原始文件的剩余部分是awk内存中前几千字节的数据。 Awk将快速继续从内存缓冲区中逐行读取并生成输出,直到缓冲区耗尽,此时awk可能会停止并留下4-65k文件。< / p>

作为旁注,如果你实际上使用awk进行扩展(例如print "PREFIX: " $0),而不是缩小(gsub(/.../, ""))数据,那么你几乎肯定会得到一个无响应awk和永久增长的文件。 :)