2012-09-15 51 views
-1

我想在文件(就地插入)中的每一行的開始處插入一個單詞後跟一個製表符,但從行號2開始到所有的行,但最後5行。在從2到結束的每一行的開始處插入文本 - 5

所以,如果一個文件有10行,我想從第2行插入第5行 - 我想在這種情況下保持第1行和第6-10行完整。

的文件可在數百萬線(目前高達10元)

sed -i "s/^/word\t/" filename 

以上的作品,但我想插入第一個和最後一個5行。還給出了一個行範圍,計算行數將是另一個操作。由於行號可能會有所不同,因此此額外操作可能會成爲開銷。尋找一個有效的解決方案。這是我到目前爲止所嘗試的:

COUNT=$((`wc -l test_csnap_delta.csv | cut -d ' ' -f 1` - 5)) 
sed -n -i '2,$COUNT s/^/word\t/' 

但是,上述操作將刪除整個文件數據。

在此先感謝。

+0

'sed -i'不能就地插入。它創建一個新文件。 –

+0

命令sed -i「s/^/word \ t /」文件名將在名爲「文件名」的文件的每一行的開始處添加文本「單詞」,後跟一個製表符,至少這是最終的結果,結果。 – user866937

+0

這感覺更像是一個「編程任務」,而不是「編程問題」。這味道很有趣,我不會吃它! –

回答

6

這工作而不precounting文件中的行的數目:

sed -ni '1{p;b}; 2{N;N;N;N}; $p; $!{N;s/^/word /;P;D}' filename 

此緩衝器五線,使在第一行的置換在緩衝器和打印和刪除它。當讀取文件中的最後一行時,將打印緩衝區而不進行任何替換。

  • 1{p;b} - 讀取第一行,打印不變,並分支到結束
  • - 當讀取第2行,追加四個線,以創建一個五線緩衝器
  • $p - 當文件的最後一行被讀取,打印仍在緩衝區不變
  • $!線 - 在當前行不是文件中的最後一行...
  • N - 下一行追加到緩衝區( PATT ERN空間)
  • s/^/word / - 讓第一線替代的緩衝
  • P - 只打印在緩衝區
  • D第一線 - 只刪除緩存中的第一行

請注意,對於包含少於6行的文件,這將無法正常工作。

這是使用AWK同樣的想法:

awk 'FNR == 1 {print; next} FNR == 2 {for (ptr = 0; ptr <= 4; ptr++) {buffer[ptr] = $0; getline}; ptr = 0} {sub(/^/, "word ", buffer[ptr]); print buffer[ptr]; buffer[ptr] = $0; ptr = (ptr + 1) % 5} END {for (i = 0; i <= 4; i++) {print buffer[(ptr + i) % 5]}}' filename > outputfile 
mv outputfile filename 

這是破了多條線路:

FNR == 1 { 
    print 
    next 
} 
FNR == 2 { 
    for (ptr = 0; ptr <= 4; ptr++) { 
     buffer[ptr] = $0 
     getline 
    } 
    ptr = 0 
} 
{ 
    sub(/^/, "word ", buffer[ptr]) 
    print buffer[ptr] 
    buffer[ptr] = $0 
    ptr = (ptr + 1) % 5 
} 
END { 
    for (i = 0; i <= 4; i++) { 
     print buffer[(ptr + i) % 5] 
    } 
} 
+0

感謝Dennis提供了使用sed和awk的詳盡答案。幫助我更瞭解sed。 – user866937

1

這樣做:

LINES=`wc -l filename | awk '{print $1}'` 
awk -v lines=$LINES 'NR > 1 && NR < lines-5 {$0 = "word\t" $0} {print}' filename 

如果你想修改filename而是將輸出重定向到一個新的文件,你需要一個臨時文件和一些額外的代碼來處理:

mv filname tmpfile 
LINES=`wc -l tmpfile | awk '{print $1}'` 
awk -v lines=$LINES 'NR > 1 && NR < lines-5 {$0 = "word\t" $0} {print}' tmpfile \ 
    > filename 
rm tmpfile 

基本上,就地編輯並不是最好的想法(就地編輯的程序通常也用於臨時文件)。如果您對這些醜陋的細節感興趣,請查看this article

+0

謝謝Ansgar - 我喜歡你的版本獲得行數,我使用剪切而不是awk,我認爲awk更好。但awk正在打印這些行。這是我的: COUNT = $((wc -l filename | cut -d''-f 1 - 5)) sed -i -n'2,$ COUNT s/^/word \ t /'文件名 雖然以上內容因某些原因完全刪除了數據。 - user866937 26分鐘前 – user866937

+0

查看更新的答案。 –

+2

@ user866937:'LINES = $(wc -l <​​文件名)' - 如果使用'wc'重定向,則不需要AWK或'cut'。 –

0

這可能會爲你(GNU SED)的工作;

sed -i '1b;:a;$q;N;2,6ba;s/^/word\t/;P;D' file 
+0

感謝您抽出寶貴時間提供幫助。 – user866937

0

如果你有足夠的內存可用,你也可以嘗試使用man 1 ed(更多信息,ed請參閱:Editing files with the ed text editor from scripts)。

# using Bash 

str="$(printf '%s\n' {1..10})" 
tab="$(printf '\t')" 

# test 
cat <<EOF | ed -s <(echo "$str") 
H 
2,\$-5s/^/word${tab}/ 
,p 
q 
EOF 

# in-place file editing 
cat <<EOF | ed -s file 
H 
2,\$-5s/^/word${tab}/ 
wq 
EOF 
相關問題