2014-07-22 64 views
1

我想替換第一行中存在的字符串,儘管它也存在於文件的其餘行中。我怎樣才能通過shell腳本來做到這一點?有人可以幫我解決這個問題。我的代碼如下。我從文件中提取第一行,然後我不知道如何進行替換。任何幫助,將不勝感激。謝謝。替換UNIX文件中的第一行上存在的字符串

夥計們 - 我想替換$ line中的字符串,並將新行寫入同一個文件中的相同位置。

代碼:

while read line 
do 
     if [[ $v_counter == 0 ]] then 
       echo "$line" 

       v_counter=$(($v_counter + 1)); 
     fi 
done < "$v_Full_File_Nm" 

樣本數據:

輸入

BUXT_CMPID|MEDICAL_RECORD_NUM|FACILITY_ID|PATIENT_LAST_NAME|PATIENT_FIRST_NAME|HOME_ADDRESS_LINE_1|HOME_ADDRESS_LINE_2|HOME_CITY|HOME_STATE|HOME_ZIP|MOSAIC_CODE|MOSAIC_DESC|DRIVE_TIME| buxt_pt_apnd_20140624_head_5records.txt 
100106086|5000120878|7141|HARRIS|NEDRA|6246 PARALLEL PKWY||KANSAS CITY|KS|66102|S71|Tough Times|2|buxt_pt_apnd_20140624_head_5records.txt 

輸出

BUXT_CMPID|MEDICAL_RECORD_NUM|FACILITY_ID|PATIENT_LAST_NAME|PATIENT_FIRST_NAME|HOME_ADDRESS_LINE_1|HOME_ADDRESS_LINE_2|HOME_CITY|HOME_STATE|HOME_ZIP|MOSAIC_CODE|MOSAIC_DESC|DRIVE_TIME| SRC_FILE_NM 
100106086|5000120878|7141|HARRIS|NEDRA|6246 PARALLEL PKWY||KANSAS CITY|KS|66102|S71|Tough Times|2|buxt_pt_apnd_20140624_head_5records.txt 

從上述採樣數據我需要更換buxt_pt_apnd_20140624_head_5records.txt與SRC_FILE_NAME字符串。

+0

UNIX shell是從中調用工具的環境。用於處理文本文件的UNIX工具是awk。所以,編寫一個awk腳本並從shell中調用它。 –

+0

您發佈的示例數據僅包含1行,但它在您的文本中聽起來像是對於在後續行中不替換字符串的解決方案非常重要,因此您應該發佈一些示例輸入/輸出以顯示您的需求方面。同樣 - 如果目標字符串在第一行出現多次,該怎麼辦?如果它是另一個字符串的一部分呢? –

回答

3

爲什麼不使用sed

sed -e '1s/fred/frog/' yourfile 

frog 1號線更換fred。如果你想要做的很到位,改變你的文件,-e前加-i

sed -e "1s/$varA/$varB/" yourfile 

如果你的「字符串」是一個變量,你可以做到這一點,以獲得變量擴大。

+2

這並不代替字符串,它取代了一個非常不同的正則表達式。 –

+0

@EdMorton - 儘管你嚴格地講是正確的,但我認爲就這個問題而言,'sed'作爲一個工具很好。看起來比'awk'簡單。 – Floris

+2

我不認爲我們應該猜測OP字符串可能包含或不包含哪些字符。到目前爲止發佈的一個例子包含一個RE元字符。在awk中相當於上面的sed腳本將是'awk'NR == 1 {sub(/ fred /,「frog」)}'yourfile'這不是比sed解決方案更復雜,你只是不會寫在awk中,因爲不像sed那樣不能支持字符串,所以你可以在awk中選擇字符串的實際工作方式,所以不要只依賴輸入數據永遠不會包含RE元字符的希望。如果有一個簡短的語法,但沒有,這將是很好的。 –

5
awk -v old="string1" -v new="string2" ' 
NR==1 && (idx=index($0,old)) { 
    $0 = substr($0,1,idx-1) new substr($0,idx+length(old)) 
} 
1' file > /usr/tmp/tmp$$ && mv /usr/tmp/tmp$$ file 

只有當它出現在的file第一行中的上述將取代string1string2

發佈的任何使用awk但不使用index的解決方案通常不起作用。對於任何使用sed的解決方案都是一樣的。原因是那些將在RE上工作,而不是字符串,因此取決於string1中存在哪些字符,因此對字符串替換表現出不理想的行爲。

看起來像的OP與SED重新更換的解決方案去所以這只是爲別人尋找替換字符串:這是一個字符串替換函數是什麼樣子,如果你幾乎不想把它內聯:

awk -v old="string1" -v new="string2" ' 
function strsub(old,new,tgt,  idx) { 
    if (idx = index(tgt,old)) { 
     tgt = substr(tgt,1,idx-1) new substr(tgt,idx+length(old)) 
    } 
    return tgt 
} 
NR==1 { $0 = strsub(old,new,$0) } 
1' file 
+0

對於'awk',是否存在'-i'類型選項,就像'sed'一樣? – Floris

+0

是的,GNU awk的新版本有'-i inplace',但是像sed一樣,它隱藏了你正在使用tmp文件的事實,它並沒有改變你正在使用它的事實。 –

+0

+1爲你編輯..你也可以工作太... :)但我發現sed更容易... – Teja

0

一個bash溶液:

file="afile.txt" 
str="hello" 
repl="goodbye" 

IFS= read -r line < "$file" 
line=${line/$str/$repl} 

tmpfile="/usr/tmp/$file.$$.tmp" 

{ 
    echo "$line" 
    tail -n+2 "$file" 
} > "$tmpfile" && mv "$tmpfile" "$file" 

注意$str上述將被解釋爲「圖案」(一種簡單的正則表達式的),其中*任意數量的任何字符匹配,?墊可以匹配任何單個字符,[abc]與括號中的任何一個字符匹配,並且[^abc](或[!abc])與括號中的任何一個字符不匹配。見Pattern-Matching

+0

這並不取代一個字符串,它取代了一個非常不同的正則表達式。 –

+0

@EdMorton更改爲「bash」解決方案。感謝指針。 – ooga

+0

這不是仍然在RE上運行,而不是字符串?它現在還有其他問題,例如,它會在輸入行的任何位置用字符串製表符替換字符串'\ t',並去掉任何前導/尾隨空白,並且如果您未能創建tmp文件,您原始文件的內容。 –