提问人:Enialis 提问时间:9/17/2023 更新时间:9/18/2023 访问量:86
Bash 脚本,用于将行的内容替换为后续行中的信息 (sed)
Bash script to replace content of line with information in a consequent line (sed)
问:
我有一个 File.txt,在方括号 [] 中包含的后续行中列出了几个项目和其他详细信息:
item name1,
item name2,
item name3,
item name4,
some text
on several lines
detail name1;
detail name2[moreinfo];
detail name3[can contain numbers and characters:1];
detail name4;
我想修改它,以便在前面的行中附加每个项目的详细信息,以获得以下预期输出:
item name1,
item name2[moreinfo],
item name3[can contain numbers and characters:1],
item name4,
some text
on several lines
detail name1;
detail name2[moreinfo];
detail name3[can contain numbers and characters:1];
detail name4;
当项目数量未知时,是否有任何简单的 sed 表达式来执行此操作? 我想要这样的东西:
sed -i '/detail \(.*\)\[\(.*\)\]/ s/item \1/item \1\[\2\]/g' File.txt
但我知道反向引用不是这样工作的。
答:
4赞
choroba
9/17/2023
#1
下面是一个Perl解决方案:
perl -0777 -pe 's/^item (.*),(?=(?:.|\n)*^detail \1(\[.*\]))/item $1$2,/mg'
它使用 (可以缩短为 Perl 5.36 之后)将整个文件作为单个字符串读入。替换使用前瞻断言来搜索相应的详细信息。-0777
-g
(?=...)
评论
2赞
Gilles Quénot
9/17/2023
perl -g
使用 Perl >= 5.36 而不是-0777
0赞
choroba
9/17/2023
@GillesQuénot:感谢您的评论,我已经更新了答案。
1赞
Ed Morton
9/17/2023
#2
使用和任何:tac
awk
$ tac file |
awk -F'[[ ,;]' '
($1 == "detail") && match($0,/\[.*]/) { det[$2] = substr($0,RSTART,RLENGTH) }
($1 == "item") && ($2 in det) { sub(/,$/,""); $0 = $0 det[$2] "," }
{ print }
' |
tac
item name1,
item name2[moreinfo],
item name3[can contain numbers and characters:1],
item name4,
some text
on several lines
detail name1;
detail name2[moreinfo];
detail name3[can contain numbers and characters:1];
detail name4;
0赞
potong
9/17/2023
#3
这可能对你有用 (GNU sed):
sed -E 'H;$!d;x
:a;s/(\nitem ([^,]+))(,.*\ndetail \2(\[[^[]+\]);)/\1\4\3/;ta;s/.//' file
将文件放入保留空间,然后对项目和详细信息使用相同名称的模式匹配来迭代替换,在匹配的项目名称后在详细信息后面插入一个括号字符串。当没有其他匹配项时,删除引入的前导换行符并打印结果。
稍短的替代解决方案:
sed -zE ':a;s/(item ([^,]+))(,.*detail \2(\[[^[]+\]);)/\1\4\3/;ta' file
1赞
ufopilot
9/17/2023
#4
awk '
FNR==NR{
if ($0 ~ /^detail /){
sub(/^detail /,"item ")
sub(/;$/,",")
key=value=$0
sub(/\[.*\]/,"",key)
a[key] = value
}
next
}
{
if ($0 in a)
print a[$0]
else
print
}
' file file
评论
sed
)sed
nameX
item name5[some_info]
details name5[more_info]