-1

我想在文件中的每一行的开头插入一个单词,后跟一个制表符(就地插入),但从第 2 行开始到除最后 5 行之外的所有行。

因此,如果一个文件有 10 行,我想从第 2 行插入到第 5 行——在这种情况下,我想保持第 1 行和第 6-10 行不变。

该文件可以有数百万行(目前最多 1000 万行)

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

这缓冲了五行并在缓冲区中的第一行进行替换并打印并删除它。当读取文件中的最后一行时,将打印缓冲区而不进行任何替换。

  • 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

这可能对你有用(GNU sed);

sed -i '1b;:a;$q;N;2,6ba;s/^/word\t/;P;D' file
于 2012-09-16T22:15:37.077 回答
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 回答