2010-02-25 63 views
4

我想用include('替換一組文件中的所有include('./。我試圖使用awk如下:awk替換單引號

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

它引發我這個錯誤。

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

任何幫助,將不勝感激。

+1

是awk某種原因的特定要求?你應該真的使用sed。 'sed -i's/include(\'。\ // include(\'/ g'* .php' – 2010-02-25 09:34:21

+1

sed,awk,都可以做這個工作。 – ghostdog74 2010-02-25 09:55:24

+0

你試過了這裏的doc嗎?那樣你沒有與逃避打擾 – 2010-02-25 09:57:52

回答

12

@OP,你可以嘗試使用八進制代碼爲單引號(\047)和正斜槓(\057),例如

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

終於有了工作,非常感謝 – GeekTantra 2010-02-25 09:54:38

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 

你有沒有嘗試沒有esacping任何

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

不工作這些錯誤裁剪... awk:警告:轉義序列\'''視爲普通''' awk:warning:轉義序列\'\('視爲普通\'' (' awk:(FILENAME = xyz.php FNR = 1)致命的:無與倫比的(或\(:/include('.// – GeekTantra 2010-02-25 09:33:27

+0

@GeekTantra我沒有控制檯或者安裝了awk,測試以上這些示例.. – ant 2010-02-25 09:40:47

+0

這些都沒有幫助...... – GeekTantra 2010-02-25 09:45:43

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/ is a constant regular expression; any string (constant or variable) may be used as a regular expression, except in the position of an isolated regular expression in a pattern.

因此,理論上,您使用的字符串形式應該工作。經驗上說,它沒有;我得到的代碼與您的代碼基本相同。而且你的shell引用是正確的,這是不平凡的。

有些時候,Perl的可能會更容易(因爲你可以選擇任意分隔符來標記正則表達式邊界):

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

此命令的工作原理,但僅適用於包含一個或兩個類似語句的簡單文件類型...足夠與大量的單引號的大文件,並削減它似乎搞亂了一切。我也得到這個錯誤: awk:warning:轉義序列'\('視爲普通'(' – GeekTantra 2010-02-25 09:49:18

+0

@GeekTantra:這是你需要使用腳本文件的地方:'awk -f file * .php'。那麼就不必與shell的對引號的解釋以及awk對引用的解釋作鬥爭,這使得整個堆棧變得更加容易。注意:MacOS的awk沒有給出,但是括號前的反斜槓替換字符串是不需要的 - 你的'awk'是正確的。 – 2010-02-25 09:57:47

+0

在'gsub'中使用雙引號有它的用途,例如,如果用正斜槓'/'代替,可以用'gsub(「/」,「」)'代替'gsub(/ \ //,「」)' – ghostdog74 2010-02-25 10:23:30

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,輸入文件本身,用於寫截斷,即磁盤上的文件大小重置爲0。此時,原始文件中剩餘的所有內容都是awk內存中的前幾個千字節。 Awk將高興地繼續從內存緩衝區逐行讀取併產生輸出,直到緩衝區耗盡,此時awk可能會停止併爲您留下4-65k文件。

作爲一個側面說明,如果你實際上是用awk擴展(例如print "PREFIX: " $0),不縮水(gsub(/.../, "")),數據,那麼你幾乎肯定會與非響應awk和永遠成長文件結束。 :)

+0

sed,awk,都可以做這個工作 – ghostdog74 2010-02-28 03:26:25

+0

可以少說引用/轉義級別:)但是真正不可原諒的部分,無論使用哪種(awk或sed),都是埃森在讀取第一行之後,即截斷每個PHP文件,即,如果該文件比awk的/ sed的讀取緩衝區大,他只是將其文件截斷爲同樣多的字節。 – vladr 2010-02-28 04:05:00

+0

awk實際上爲我做了這份工作。它不是關於使用sed或awk關於哪一個更舒適。 – GeekTantra 2010-02-28 04:13:26