Pan*_*nki 17
例如,使用以下命令从底部删除第 4 行sed
:
tac input | sed '4d' | tac
Run Code Online (Sandbox Code Playgroud)
要覆盖输入文件:
tmpfile=$(mktemp)
tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input
Run Code Online (Sandbox Code Playgroud)
纯sed
:
如果n是 1:
sed '$ d'
Run Code Online (Sandbox Code Playgroud)
这很简单:如果是最后一行,删除模式空间,这样它就不会被打印出来。
如果n大于 1(并且可用作$n
):
sed "
: start
1,$((n-1)) { N; b start }
$ { t end; s/^//; D }
N
P
D
: end
"
Run Code Online (Sandbox Code Playgroud)
注意$((n-1))
在sed
启动前由外壳展开。
这个片段
: start
1,$((n-1)) { N; b start }
Run Code Online (Sandbox Code Playgroud)
在模式空间中存储n -1 行。如果sed
在此循环中到达输入流的末尾,将自动打印模式空间(从末尾开始没有第 n 行,不会删除任何行)。
假设有更多的输入。然后,在我们到达最后一行之前,迭代这个片段:
N # read the next line of input and append it to the pattern space
P # print the first line from the pattern space
D # delete the first line from the pattern space and start a new cycle
Run Code Online (Sandbox Code Playgroud)
这样,模式空间就是我们的缓冲区,它根据输入使输出“延迟”了几行。N
从这个片段也能够读取输入的最后一行。
读取最后一行后,将执行此操作:
$ { t end; s/^//; D }
Run Code Online (Sandbox Code Playgroud)
这段代码第一次执行时,t
不会跳转到,end
因为之前没有成功的替换。s/^//
然后执行这种无操作替换,并且模式空间中的第一行被删除 ( D
) 而不打印。这正是您要删除的行。由于D
开始了一个新的循环,同一行代码最终会再次执行。这次t
将分支到end
.
当sed
到达脚本末尾时,将自动打印模式空间。这样所有剩余的行都会打印出来。
该命令将为n=2
(有效)和n=1
(无效)生成相同的输出。我试图找到一个不管n都有效的解决方案。我失败了,因此是n为 1的特殊情况。