-1

ファイルの各行の先頭に単語の後にタブ文字を挿入したい(インプレース挿入)が、行番号2から始まり、最後の5行を除くすべての行まで。

したがって、ファイルに10行ある場合、行番号2から行番号5に挿入します。この場合、行1と6-10はそのままにしておきます。

ファイルには数百万行(現在は最大1,000万行)を含めることができます

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/' 

ただし、上記はファイルデータ全体を削除しています。

前もって感謝します。

4

4 に答える 4

6

これは、ファイル内の行数を事前に数えなくても機能します。

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

これは 5 行をバッファリングし、バッファの最初の行で置換を行い、出力して削除します。ファイルの最後の行が読み取られると、バッファーは置換を行わずに出力されます。

  • 1{p;b}- 最初の行を読み取り、変更せずに出力し、最後に分岐します
  • 2{N;N;N;N}- 行 2 が読み取られるとき、さらに 4 行を追加して 5 行のバッファーを作成します。
  • $p- ファイルの最後の行が読み込まれると、バッファに残っている行を変更せずに出力します
  • $!- 現在の行がファイルの最終行でない場合...
  • N- 次の行をバッファに追加 (パターン スペース)
  • 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]
    }
}
于 2012-09-16T20:36:10.040 に答える
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

基本的に、インプレース編集は最善のアイデアではありません(インプレース編集を行うプログラムは通常、一時ファイルでも機能します)。醜い詳細に興味がある場合は、この記事をご覧ください。

于 2012-09-15T23:39:07.753 に答える
0

十分な RAM が利用できる場合は、使用することもできますman 1 ed(詳細については、スクリプトから ed テキスト エディターを使用してファイルを編集するedを参照してください)。

# 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
于 2013-05-08T12:07:25.997 に答える
0

これはうまくいくかもしれません(GNU sed)。

sed -i '1b;:a;$q;N;2,6ba;s/^/word\t/;P;D' file
于 2012-09-16T22:15:37.077 に答える