2010-07-02 73 views
1

我想寫一個可以編輯自己的bash腳本。我試圖使用的代碼行是:編輯自己的Bash腳本

sed "s/$STRING_TO_REPLACE/$NEW_STRING/" < $0 > $0 

但是在運行腳本後,我最終得到一個空文件。有什麼建議麼?

我正在創建一個腳本,其中包含兩個包含默認值的變量。唯一的問題是,這些默認值對於將被使用的許多臺站中的每一個將是不同的。我寧願沒有運行這些工作站的人員必須打開腳本並自己編輯默認設置,所以我想包括在腳本中更改默認設置的功能。我的要求之一是腳本必須是自我包含的;沒有其他文件伴隨腳本,並且沒有環境變量。這需要腳本能夠編輯自己。

+1

我很好奇,是什麼,實驗多態腳本,或者你真的認爲這將是有益的。 – 2010-07-02 19:15:30

+0

這可以幫助:http://stackoverflow.com/questions/3055005/bash-is-it-ok-to-use-same-input-file-as-output-of-a-piped-command – Amro 2010-07-02 19:17:51

+0

考慮擁有2腳本。 1是一個即時創建另一個然後執行它的控制器。 – DwB 2013-09-18 16:37:10

回答

2

如果要使用sed執行就地替換,請使用-i開關。

我不推薦重寫正在執行的腳本。我不確定這是否可行,但如果是這樣,它肯定會很有趣(閱讀:困難)代碼來保持:-)

+0

我明白這很醜陋。我不得不想另一種方式來做到這一點。 – 2010-07-05 20:14:34

+0

他不需要在執行過程中編輯腳本。當某個條件滿足時,他可以簡單地強制腳本退出,如布爾值爲true或false,然後讓一個從屬節點(外部腳本)編輯主節點(主腳本)並根據需要更改適當的行。 – Yokai 2016-12-14 07:07:30

1

首先,這是一個非常糟糕的想法,我無法想象任何不能被某些東西所覆蓋的用例。

發生這種情況的原因是,當您執行>文件時,它會以讀取模式打開文件並將其截斷爲0長度,並且輸入無法讀取。您需要使用臨時文件。你可以看到更多信息here

+1

他可以簡單地強制腳本在滿足某些條件時退出,如布爾值爲true或false,然後讓一個從節點(外部腳本)編輯主節點(主腳本)並根據需要更改適當的行。或者他甚至可以使用配置文件來保存即時數據更改,讓腳本退出,然後重新運行新的配置更改。我假設他可能正在測試小型單純形A.I.理論。 (即自校正碼)。 Bash對於測試諸如此類的小型單形理論來說非常合適。 – Yokai 2016-12-14 07:12:19

0

Perl處理編輯。試試這個:

perl -npi -e "s/$STRING_TO_REPLACE/$NEW_STRING/g" < $0 
+0

這是行不通的,因爲你在STDIN上提供文件,所以沒有文件就地修改。刪除'<'爲它做你正在嘗試。 – Daenyth 2010-07-02 20:03:36

3

你正在嘗試讀取和寫入同一個流,這是一個糟糕的編程習慣,通常會導致錯誤。

這是你應該做的:

  1. 寫入到一個臨時文件
  2. 刪除原始文件
  3. 重命名臨時到原來的文件名

    sed的「S/$ STRING_TO_REPLACE/$ NEW_STRING /「< $ 0> temp

    rm $ 0

    MV臨時$ 1

我沒有做過的,而bash的腳本程序,因此確認我有權命令。

+0

rm不是必需的,它應該是「mv temp $ 0」,並且我必須在最後執行chmod以使新文件成爲可執行文件。除此之外,它的工作原理:)我不知道我可以刪除腳本,而它正在運行。 – 2010-07-02 19:24:26

0

還記得你應該不是編輯一個正在運行的shell腳本。閱讀my answer至問題Edit shell script while it's running

+0

他不需要在執行過程中編輯腳本。當某個條件滿足時,他可以簡單地強制腳本退出,如布爾值爲true或false,然後讓一個從屬節點(外部腳本)編輯主節點(主腳本)並根據需要更改適當的行。我假設他可能正在測試小型單純形A.I.理論。 (即自校正碼)。 – Yokai 2016-12-14 07:10:14

0

我在做什麼,我也建議,有一個配置文件($ HOME/.myscript.cfg)並讓腳本檢測它的存在(和版本)並相應地創建/更新它。這樣,第一次運行就可以提出問題,隨後的運行可以完成他們的工作,而不會給運營商帶來重複的問題。

0

但運行腳本後,我最終得到一個空文件。有什麼建議麼?


有點遲來的迴應......一個可能的解決方案是,你的腳本可以腳本的退出命令後,包含修改設置

,以避免任何東西,但這些設置意外更改,這將是一個好主意,使用適當的前綴,像這樣:

@SETTINGS 
@setting-homepage=http://www.goatse.cx 
@setting-dns=4.4.2.2 
下面

是改變兩個變量的例子:一個指定的默認瀏覽器主頁(默認:www.goatse.cx,新:www.google.com),另一個用於更改DNS(默認:4.4.2.2,新:8.8.8.8)。警告

的sed的



字用於修改包含所需的設置行號的內容。如果在這裏出現錯誤,將會出現spaz,並用sed相關的瘋狂覆蓋腳本中的每一行。一種解決方案可能是讓腳本編寫另一個腳本,然後用它來修改原始腳本。另一種方法可能是在確認匹配存在之後,包含一個僅執行sed替換的條件語句。或者可能更簡單,匹配所需的設置字符串,而不僅僅是行號。

編輯:它似乎試圖執行字符串匹配與sed結果在一些奇怪的腳本自噬。我想你需要指定在exit命令下面的行號。



#!/bin/bash 

# find settings and extract their values 
settingDefaultHomepage=$(grep ^@setting-homepage $0 | sed 's/@setting-homepage=*//') 
settingDefaultDNS=$(grep ^@setting-dns $0 | sed 's/@setting-dns=*//') 


echo "Default browser homepage = $settingDefaultHomepage" 
echo "Default DNS = $settingDefaultDNS" 


# find line number of setting, to be used when modifying the value 
settingLineHomepage=$(awk '/^@setting-homepage/ {print FNR}' $0) 
settingLineDNS=$(awk '/^@setting-dns/ {print FNR}' $0) 

echo "Line of setting for browser homepage = $settingLineHomepage" 
echo "Line of setting for DNS = $settingLineDNS" 



# modify the settings using line number above 
sed -i $settingLineHomepage's/.*/@setting-homepage=www.google.com/' $0 
sed -i $settingLineDNS's/.*/@setting-dns=8.8.8.8/' $0 



exit 


@SETTINGS 
@setting-homepage=www.goatse.cx 
@setting-dns=4.4.2.2 



+0

遲來的是輕描淡寫。我獲得了學位,並有3個工作之間問這個問題和你的答案:P – 2015-06-19 21:28:43

+0

大聲笑,在這裏我希望你被困在同樣的死衚衕工作。 – faustus 2015-06-19 21:47:23