Bash:在文件中弹出行[关闭]

问题描述 投票:0回答:3

我需要用 bash 读取文件并删除请求行?有些类似于 弹出/推送功能。

我该怎么做?

bash line
3个回答
17
投票

对!
sed
会很好地完成这项工作!

简介

正如 @Lee Netherton 的评论正确指出的那样,当运行 进行 inplace 编辑时,强烈建议使用备份! (当然,一旦完成,您的脚本必须在继续之前测试

sed
命令是否成功...)

测试用例

所以让我们快速构建一个测试文件:

printf "Line #%2d\n" {1..7} >file

对于 pop(从堆栈顶部开始):

作为真正的推送/弹出,以下命令返回所需的行将其从指定文件中删除。

sed -e \$$'{w/dev/stdout\n;d}' -i~ file
Line # 7

然后

cat file
Line # 1
Line # 2
Line # 3
Line # 4
Line # 5
Line # 6

对于 shift(从堆栈底部开始):

sed -e 1$'{w/dev/stdout\n;d}' -i~ file
Line # 1

用于拼接(堆栈中的随机访问)

(删除第n行)

lineNum=3
sed -e $lineNum$'{w/dev/stdout\n;d}' -i~ file
Line # 4

对于push(到堆栈顶部):

printf -v val "Line #%2d" 28
echo "$val" >>file

注意:无论如何,这可以通过使用

sed
来完成:

sed -e "\$a$val" -i~ file

(其中

$a
不是变量,而是 sed 位置
$
,这意味着 在文件末尾
a
命令,这意味着 追加到当前行之后

对于 unshift(到堆栈底部):

printf -v val "Line #%2d" 62
sed -e 1i"$val" -i~ file

最后

cat file
Line #62
Line # 2
Line # 3
Line # 5
Line # 6
Line #28

进入变量

当然,目标是将它们检索到变量中。根据您使用的是 还是其他 POSIX ,您可以使用以下之一:

lastline=`sed -e \\\$$'{w/dev/stdout\n;d}' -i~ file`
echo $lastline 
Line #28

lastline=$(sed -e \$$'{w/dev/stdout\n;d}' -i~ file)
echo $lastline 
Line # 6

read lastline < <(sed -e \$$'{w/dev/stdout\n;d}' -i~ file)
echo $lastline 
Line # 5

2018 年新年新增

新年快乐!

简单的 bash 函数示例:

fpop() { local v n=$'\n';read -r v < <(
    sed -e $'${w/dev/stdout\n;d}' -i~ "$1")
    printf ${2+-v} $2 "%s${n[${2+2}]}" "$v"
}
fshift() { local v n=$'\n';read -r v < <(
    sed -e $'1{w/dev/stdout\n;d}' -i~ "$1")
    printf ${2+-v} $2 "%s${n[${2+2}]}" "$v"
}
fsplice() {
    [ "$2" ] || return ; local v n=$'\n';read -r v < <(
    sed -e $2$'{w/dev/stdout\n;d}' -i~ "$1");
    printf ${3+-v} $3 "%s${n[${3+3}]}" "$v"
}
fpush() { sed -e "\$a$2" -i~ "$1"; }
funshift() { sed -e "1i$2" -i~ "$1"; }

注:

printf ${2+-v} $2 "%s${n[${2+2}]}" "$v"
行是我在函数中经常使用的一种技巧。如果作为第二个参数提交,此行将填充一个变量。否则,此行将添加一个 newline 并打印到
STDOUT

  • ${2+-v}
    将解析为
    -v
    $2
    存在,然后
    -v $2
    填充变量。
  • 如果
  • ${n[${2+1}]}
     不存在,
    ${n[0]}
    将显示
    $'\n'
    $2
    换行
    )。

小运行样本:

printf "Line #%2d\n" {3..12} >file   

fpop file
Line #12
fpop file myvar
echo $myvar
Line #11

fshift file
Line # 3
fshift file myvar
echo $myvar
Line # 4

fsplice file 3 
Line # 7
fsplice file 3 myvar
echo $myvar
Line # 8

funshift file "Line # 192"
fpush file "Line # 42"

cat file
Line # 192
Line # 5
Line # 6
Line # 9
Line #10
Line # 42

declare -p myvar
declare -- myvar="Line # 8"

(变量 myvar 不包含 newline。)

而且(我无法抗拒!;-):

fpop file myvar
echo $((9? ${myvar#*#} :-b))
42

1
投票

sed 是面向流式传输的,您可以使用适合编辑文件的 ed。

#/usr/bin/sh

ed -s filename <<EDSCRIPT
1p
d
wq
EDSCRIPT
  1. 将第一行打印到标准输出。
  2. 删除它。
  3. 保存并退出。

如果你想做其他事情,

1,3
用于第 1 行到第 3 行。
$
用于最后一行。


0
投票

您可以使用

sed
删除特定行号或与给定模式匹配的行:

$ cat file
line 1
line 2 
line 3 
line 4
line 5

$ sed -i '3d' file             # Delete the 3rd line
line 1
line 2 
line 4
line 5    

$ sed -i '/^line 4$/d' file    # Delete the line that matches the pattern
line 1
line 2 
line 3 
line 5


$ sed '$d' file                # Delete the last line in the file
line 1
line 2 
line 3 
line 4

但是您将无法

push
这些线路回来..

© www.soinside.com 2019 - 2024. All rights reserved.