我想在文件中的每一行的开头插入一个单词后跟一个制表符(就地插入),但是从第2行到所有行但最后5行。
因此,如果一个文件有10行,我想从第2行插入到第5行 - 我希望在这种情况下保持第1行和第6-10行完整。
该文件可以有数百万行(目前高达1000万)
sed -i "s/^/word\t/" filename
上述工作,但我想插入第一行和最后五行。同样给出一个行范围,计算行数将是另一个操作。由于行号可以变化,因此这种额外的操作可能成为开销。寻找有效的解决方案。这是我到目前为止所尝试的:
COUNT=$((`wc -l test_csnap_delta.csv | cut -d ' ' -f 1` - 5))
sed -n -i '2,$COUNT s/^/word\t/'
但是,上面的内容是删除整个文件数据。
提前致谢。
答案 0 :(得分: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行时,再追加四行以创建五行缓冲区$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]
}
}
答案 1 :(得分: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。
答案 2 :(得分:0)
这可能适合你(GNU sed);
sed -i '1b;:a;$q;N;2,6ba;s/^/word\t/;P;D' file
答案 3 :(得分: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