2011-09-14 145 views
2

我有一個包含這樣的平面文件追加到特定線路的平面文件:如何使用shell腳本

11|30646|654387|020751520 

11|23861|876521|018277154 

11|30645|765418|016658304 

使用shell腳本,我想追加一個字符串在這個特定的行文件,如果這些行包含特定的字符串。

例如,在上述文件中,含有23861線,我想追加一個字符串「加工」結尾,以便文件變爲:

11|30646|654387|020751520 

11|23861|876521|018277154|Processed 

11|30645|765418|016658304 

我可以用sed追加字符串到文件中的所有行,但是如何爲特定行執行?

回答

1

使用以下AWK-腳本:

$ awk '/23861/ { $0=$0 "|Processed" } {print}' input 
11|30646|654387|020751520 

11|23861|876521|018277154|Processed 

11|30645|765418|016658304 

,或者使用sed

$ sed 's/\(.*23861.*$\)/\1|Processed/' input 
11|30646|654387|020751520 

11|23861|876521|018277154|Processed 

11|30645|765418|016658304 
+1

或'awk'BEGIN {OFS = FS =「|」}/23861/{$(NF + 1)=「Processed」} {print}'' –

1

使用替換命令:

sed -i~ -E 's/(\|23861\|.*)/\1|Processed/' flat.file 

(注:-i~進行置換如果您不想修改原始文件,請將其保留文件)。

+0

謝謝。在線替換正是我正在尋找的,但sed -i似乎不適用於我的AIX機器。它給出:sed:不是一個可識別的標誌:i 用法:sed [-n] [-u]腳本[文件...] sed [-n] [-u] [-e Script] ... [ f Script_file] ... [文件...] 也許這在AIX上不受支持 – AKS

+0

sed -i實際上並沒有在任何地方做任何事情;它只是掩蓋了將輸出寫入臨時文件的過程,然後它會在原始文件上移動,這很容易通過手工完成。 – flabdablet

+0

@flabdablet:誰在乎力學? 'sed -i〜... abc'更方便 - 更不用說容易出錯 - 比'sed ... abc> .abc.tmp && mv abc abc〜&& mv .abc.tmp abc'。 –

0

您可以使用shell

while read -r line 
do 
    case "$line" in 
    *23681*) line="$line|Processed";; 
    esac 
    echo "$line" 
done <file> tempo && mv tempo file 
3

我會做這種方式

sed '/\|23861\|/{s/$/|Something/;}' file 

這與馬塞洛的答案,但並不需要延長的表情和是的,我認爲,一點清潔劑。

首先,將管之間23861

/\|23861\|/ 

隨後的比賽線路,這些線路,以字符串|Something

{s/$/|Something/;} 

如果你想要做多,置換結束的行其中一個你可以簡單地列出它們

sed '/\|23861\|/{s/$/|Something/;};/\|30645\|/{s/$/|SomethingElse/;}' file 
+0

這確實比較乾淨。但是,我理想地嘗試在同一個文件內部修改內聯,而不必將輸出重定向到不同的文件(或返回到同一文件)。 sed -i似乎不適用於我的AIX機器。如果沒有其他選擇進行內聯替換,我將與您的答案一起去。謝謝。 – AKS

+0

@AKS:如果AIX的'sed'不支持'-i',你可以安裝'gsed'嗎?或者它已經安裝了? – Sorpigal

+0

@Sorpigal:同意。我試圖找出如何通過正則表達式來處理一條線。手冊頁沒有幫助。 –

0

sed is只是一個流版本ed,它有一個類似的命令集,但是被設計用來編輯文件(據稱是交互式的,但是除非你擁有的是these之一,否則你不想這樣使用它)。類似於

field_2_value=23861 
appended_text='|processed' 
line_match_regex="^[^|]*|$field_2_value|" 
ed "$file" <<EOF 
g/$line_match_regex/s/$/$appended_text/ 
wq 
EOF 

應該讓你那裏。

請注意,$ ... /s/$/ ...是由外殼擴展,因爲是$ line_match_regex$ appended_text,因爲沒有這樣的東西作爲$/ - 而不是它是通過AS-是過去了,它會將其解釋爲文本替代品($被正則表達式表示爲「行尾」)。

在sed中執行相同任務的語法,如果您想要將其轉換爲流而不是文件,則非常相似,除非您在正則表達式地址之前不需要前導g:

sed -e "/$line_match_regex/s/$/$appended_text/" "$input_file" >"$output_file" 

你需要確保你把field_2_valueappended_text絕對不包含斜線的值,因爲ED的小號命令使用那些分隔符。

如果他們可能會做,而你使用bash或其他一些貝殼,允許通過置換\/$ {//名稱查找/替換}參數擴展語法,可以解決這些問題了上飛在擴展這些變量期間每/。因爲bash中也使用/作爲替代分隔符,並且也使用\作爲轉義字符,這最終看起來可怕:

appended_text='|n/a' 
ed "$file" <<EOF 
g/${line_match_regex//\//\\/}/s/$/${appended_text//\//\\/}/ 
wq 
EOF 

,但它確實工作。 n注意這兩個sed的需要尾隨替換文本後/S /查找/替換/而bash的$ {//名稱查找/替換}語法不。