请教一下 shell 文本处理大神

2023-02-21 19:35:09 +08:00
 toyst

想把这段

DEFAULT_PACKAGES += asdf asdf wfqw sdfg \
jljldja ldoahf lajsdf \
lj.msaldj jlasd-ewk

$(eval $(call BuildTarget))

xorrisofs -v 2>&1 | grep xorriso \

替换成

DEFAULT_PACKAGES += ghj65 dfg sfd \
ljdfg sdlgjl \
jsflj asda-sadf

$(eval $(call BuildTarget))

xorrisofs -v 2>&1 | grep xorriso \

用 shell 怎么写啊

2525 次点击
所在节点    Linux
14 条回复
zhlxsh
2023-02-21 19:43:08 +08:00
没看出来啥规律,DEFAULT_PACKAGES 完全替换掉吗?或者说说你遇到啥问题了
toyst
2023-02-21 20:04:04 +08:00
@zhlxsh 就是替换 后面到$(eval 前面那一坨
yang3121099
2023-02-21 22:01:27 +08:00
可以使用 sed 命令对文本进行替换。假设这个文本存储在名为 text.txt 的文件中,可以使用以下命令:

vbnet Copy code
sed -i 's/asdf asdf wfqw sdfg \\/ghj65 dfg sfd \\/g; s/jljldja ldoahf lajsdf \\/ljdfg sdlgjl \\/g; s/lj.msaldj jlasd-ewk/jsflj asda-sadf/g' text.txt
这个命令将对 text.txt 中的文本进行替换,并将结果写回到原文件。具体来说,使用 sed 命令的 -i 选项表示原地编辑,s/old/new/g 表示将 old 替换为 new ,\\ 表示换行符,多个替换操作用分号隔开。

注意,为了避免误操作,请先备份原文件

————chatgpt
boboliu
2023-02-21 22:24:39 +08:00
a="input"
echo "${a/DEFAULT_PACKAGES \+\=*$/DEFAULT_PACKAGES += aa $'\n' bb $'\n\n'$}"

多看 man
boboliu
2023-02-21 22:25:35 +08:00
@boboliu #4 忘了插 // ,自己解决一下.jpg
jackmod
2023-02-21 22:27:52 +08:00
sed -z
以 0 作为行尾,替换 DEFAULT_PACKAGES += 和 $(eval 之间的部分即可
boboliu
2023-02-21 22:29:27 +08:00
@boboliu #5 应该插 \\,另:bash only
koebehshian
2023-02-21 22:53:04 +08:00
可以利用 awk 和记录分隔符 RS 和 ORS 来替换;但最后一条记录不需要分隔符,所以改良了一下:
把要替换的字符串设为输入记录分隔符 RS ,把输出记录分隔符 ORS 设为空,awk 遍历记录回调中,读取当前记录索引 FNR ,如果为 1 ,则输入$0 和要替换的字符串,否则只输出$0
listenerri
2023-02-21 23:13:01 +08:00
```
#!/bin/bash

# 从以 DEFAULT_PACKAGES 开头的行开始,
# 直到以非反斜杠结束的行为止,将其替换为指定内容
sed '/^DEFAULT_PACKAGES.*/,/.*[^\\]$/c \
DEFAULT_PACKAGES += ghj65 dfg sfd \\\
ljdfg sdlgjl \\\
jsflj asda-sadf' test.txt

# 命令假设待处理文件名为 test.txt

```
listenerri
2023-02-21 23:16:58 +08:00
@listenerri #9 如果需要直接修改目标文件,为 sed 命令增加 -i 参数
pagxir
2023-02-21 23:38:00 +08:00
cat << "EOF" |
DEFAULT_PACKAGES += asdf asdf wfqw sdfg \
jljldja ldoahf lajsdf \
lj.msaldj jlasd-ewk

$(eval $(call BuildTarget))

xorrisofs -v 2>&1 | grep xorriso \
EOF
sed '/DEFAULT_PACKAGES/{:l; N; /\\/{s#\\\n#@#g; bl;}}'
Owenjia
2023-02-21 23:54:36 +08:00
简单写了下,假设原文本保存在 testdata 中,使用 sed 匹配起始行,然后循环读取,直到读到空行,再匹配字符进行替换,将输出的文件重定向到新文件即可:

sed -n '/^DEFAULT_PACKAGES / { h; :loop; n; H; s/^$//; T loop; x; s/+= .*$/+= ghj65 dfg sfd \\\nljdfg sdlgjl \\\njsflj asda-sadf\n/};p' testdata > newdata
drwx
2023-02-22 10:37:59 +08:00
@jackmod 原来 sed 也有类似`find -print0`这样的选项啊,第一次知道,学到了,感谢!

原来也很头疼 sed 处理跨行的文本,网上搜到的方法要不就是要用 sed 的 hold space, pattern space 来操作,要不就是 awk 写一大片处理逻辑,用 sed -z 就方便多了。

@toyst 我给个具体的语句:

```bash
sed -z -i -e 's@asdf asdf wfqw sdfg \\\njljldja ldoahf lajsdf \\\nlj.msaldj jlasd-ewk@ghj65 dfg sfd \\\nljdfg sdlgjl \\\njsflj asda-sadf@' a.txt
```
yiyu1211
2023-02-22 18:13:48 +08:00
awk '/DEFAULT_PACKAGES/{print("DEFAULT_PACKAGES += ghj65 dfg sfd \\");getline;print("tljdfg sdlgjl \\");getline;print("tjsflj asda-sadf");next} 1' text.txt

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/918034

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX