2010-02-22 43 views
6

我已將全局名稱空間中的類移動到特定的名稱空間中。我也改變了類名。我想將使用這些類的所有源文件轉換爲新格式。我正在考慮在Cygwin上使用sed文件的bash腳本或執行perl腳本。我在bash腳本中遇到了麻煩。用於更改C++類名稱的腳本

這裏是我試圖執行過程:

  1. 對於每個源文件,*。cpp和。 * .HPP,遞歸:
  2. 如果文件中包含的老班 名稱,然後轉換文件。
  3. 結束。

我的問題Bash腳本正在檢測文件是否包含舊的類名。我在想一個grep聲明的每個類名稱:

for f in `find . -iname \*.[ch]pp`; 
do 
    if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; then 
     sed -f conversion.sed $f 
    fi 
done 

的一個問題是,只有一個命令可以在Bash if語句,使用此語法:

if grep "Field_Unsigned_Short" $f; 

,所以我不能做邏輯或的grep s。

我可以執行一個嵌套的循環,但我不知道如何breakBash的for循環:

OLD_CLASS_NAMES="Field_Blob_Medium Field_Boolean Field_Unsigned_Int" 
for f in `find . -iname \*.[ch]pp`; 
do 
    for c_name in $OLD_CLASS_NAMES; 
    do 
    if grep $c_name $f then 
     sed -f convert.sed $f # <-- Need to break out of inner loop after this execution. 
    fi 
    done 
done 

所以我在尋找如何處理包含每個源文件的建議舊的類名稱,並將其轉換爲新的名稱。 Cygwin Bash腳本示例是首選,但Perl腳本也是可以接受的。 此外,腳本應在將轉換後的內容寫入new文件之前製作原始源文件的備份副本。

我在Windows XP和Windows Vista上運行Cygwin。

+1

cant你只是使用多個正則表達式的grep? grep -e「Field_Blob_Medium」-e「Field_Boolean」-e「Field_Unsigned_Int」... ? – lollinus 2010-02-22 21:45:37

+1

以備份每個處理過的文件: sed -i.bak -f convert.sed $ f – lollinus 2010-02-22 21:47:41

+0

'break'突破'for for循環,你可以做'if prog || prog || prog'爲邏輯OR(但在這種情況下,正則表達式更好)。 'find'通常是個不錯的主意,因爲文件名有空格時會失敗。 '把'find'變成'while'時最好。 – 2010-02-23 01:02:08

回答

2

不要回避的Perl遠:它使這類任務方便!

#! /usr/bin/perl -i.bak 

use warnings; 
use strict; 

my $old = join "|" => qw(
    Field_Blob_Medium 
    Field_Boolean 
    Field_Unsigned_Int 
); 

chomp(@ARGV = `find . -iname \*.[ch]pp -print0 | 
       xargs -0 grep -lE '($old)'`); 

unless (@ARGV) { 
    warn "$0: nothing to do!\n"; 
    exit 0; 
} 

while (<>) { 
    s[Field_Blob_Medium] [my::ns::MediumBlob]g || 
    s[Field_Boolean]  [my::ns::Bool]g  || 
    s[Field_Unsigned_Int] [my::ns::UInt]g; 

    print; 
} 

-i開關用於就地編輯。它會自動創建備份並將轉換後的結果寫入原始位置。

設置@ARGV使您可以像調用僅包含舊類名的文件*.cpp*.hpp那樣的程序。 -E切換到grep啓用擴展的正則表達式,因此非轉義的(,)|是元字符。

如果沒有命中(,即,如果@ARGV爲空),那麼沒有任何事情可做。

否則,對於每個具有舊名稱的文件(每個Perl爲您處理的機制!)的每一行,嘗試將Field_Blob_Medium重命名爲my::ns::MediumBlob等等。請注意,這些替換嘗試在第一次成功後停止,因此如果一行包含兩個不同的舊名稱,則會替換一個,而另一個將保持不變。

通常替換運算符被寫爲s///,但是您可以使用如上所述的包圍分隔符。我這樣做是爲了讓新名字左移正確。

當然這是替代您的實際替身。

最後,print可能被修改的行,這是因爲-i將它寫入更新後的源文件。

0

您可以使用grep的正則表達式選項爲您提供更多的搜索靈活性。根據您的例子:

if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; 

可能是

if [ grep -E "(Field_Blob_Medium|Field_Boolean)" ... ]; 

你可以串起來的 '|' s到你的心內容。

另外,您可以合併您的發現到您的裏grep

find . -name "*.hpp" or -name "*.cpp" | xargs grep -E ... 

...如果你想簡化環路存在。

1

這項工作在我的linux上。它管理被別人指出的各種事情:

#!/bin/bash 
OLD_NAMES="(EField_Blob_Medium|Field_Boolean|Field_Unsigned_Int)" 

find "$1" -name "*.hpp" -o -name "*.cpp" -print0 | \ 
    xargs -0 --replace grep -E "${OLD_NAMES}" {} && sed -i.save -f convert.sed {} 

什麼是重要的:

  • 用的xargs -0找到的-print0選項管理與空格的文件。它使用'空'ASCII字符作爲分隔符。 xargs的-0選項將'null'字符理解爲分隔符:正確地使用空格管理文件名。
  • 的--replace選項用於由當前處理的文件替換「{}」串
  • SED背上了一個.save
  • 的& &工作作爲快捷方式的文件的-i選項如果。表達的第二部分的工作只有在第一部分是真正的

希望它helsp, MY2C