gpt4 book ai didi

Bash/Sed - 多行 sed 操作打印行乱序

转载 作者:行者123 更新时间:2023-11-29 09:27:27 25 4
gpt4 key购买 nike

我在使用 sed 编辑日志文件时遇到了一些问题。我已经将它内置到一个函数中,该函数应该用另一个函数的输出替换两个搜索字符串之间的文本。它几乎可以正常工作,但是将行打印到日志文件中是乱序的。对于我的生活,我无法弄清楚为什么,而且我在尝试修复它时所做的大多数调整实际上都不太理想。

我的 sed 函数:

log_edit(){
"$3" > temp.txt
sed -i -n "/$1/{
:loop
n
/$2/!b loop
x
r temp.txt
G
s/$2/\n\n&/
}
p" "$FILE"
rm temp.txt
}

我使用“=== text ===”分隔符作为我的开始和停止字符串传递给函数,并使用首先构建日志的相同函数来填充临时文本文件。
问题发生在与“G”命令附近/相关的某个地方。它不是将保持模式行附加到字符串的末尾,而是将其附加到字符串的开头。

原始日志样本/期望的输出:

=== Metech ITAMS Log ===

Metech Recycling
ITAMS Hardware Report
Date: Thu Mar 2 08:01:38 PST 2017
Tech: SP

=== Manufacturer Information ===

# dmidecode 2.12
...

不幸的是,我得到的输出看起来像这样:

=== Manufacturer Information ===

=== Metech ITAMS Log ===

Metech Recycling
ITAMS Hardware Report
Date: Fri Mar 3 09:39:02 PST 2017
Tech: SS

# dmidecode 2.12
...

有人能帮助我理解我做错了什么,或者提出修复建议吗?这是我向 SO 提出的第一个问题,如果需要更多信息,我很乐意提供。提前致谢。

编辑 #1:根据要求调用函数的代码片段:

        2)
printf "\n"
text_prompt "Please enter Tech initials: "
set_tech_id
text_prompt "Please enter Traveler ID: "
set_travel_id
mv "$FILE" "$TRAVEL_ID $TECH_INITIALS"
FILE="$TRAVEL_ID $TECH_INITIALS"
log_edit "=== Metech ITAMS Log ===" \
"=== Manufacturer Information ===" "print_header"
unset TECH_INITIALS
unset TRAVEL_ID
;;

这是菜单功能的一部分,包含整个内容就太过分了,请注意,将使用不同的开始/停止字符串多次调用 log_edit(尽管所有调用都遵循 === ===模式),但通常调用不同的函数来填充 temp.txt。

编辑 2:为了更加清晰,我想我应该添加用 $3 调用的函数:

print_header(){ #Prints log header.
print_div "Metech ITAMS Log"
printf "Metech Recycling\nITAMS Hardware Report\nDate: $(date)\nTech: %s\n" \
"$TECH_INITIALS"
}

并且 print_header 调用 print_div:

print_div(){ #Prints a divider.  Required parameter: $1=Text for divider.
printf "\n=== %s ===\n\n" "$1"
}

编辑 3:为清楚起见,我的问题是 $2 字符串在 temp.txt 内容之前而不是之后写入日志。

最终编辑:找到了解决方案。我想我会在下面发布工作代码,以防它对其他人有帮助。我的问题的很大一部分是对 sed 如何使用“r”命令的误解。这个解决方案的另一部分来 self 仍然不理解的已接受答案,那就是添加反斜杠的替代命令,这是使其工作的关键。我不知道为什么会这样,但确实如此。

log_edit() { #Works!!
"$3" > temp.txt
sed -i -n '/^'"$1"'$/ {
:loop
n
/^'"$2"'$/!b loop
i\
'"$(sed 's/\\/\\&/g;s/$/\\/' -- "temp.txt")"'

#Blank line terminates i command.
}
p' "$FILE"
rm temp.txt
}

最佳答案

r 命令在下一次读取 之前复制文件,而不是在评估文件时,并且不修改模式空间。但是,该文件可以作为 i 命令的一部分插入到脚本中:

log_edit() {
sed -n '/^'"$1"'$/ {
p
:loop
n
/^'"$2"'$/!bloop
i\
'"$("$3" | sed 's/^[[:space:]]/\\&/;s/\\/\\&/g;s/$/\\/')"'

# The blank line above is part of the `i' command,
# and appends a newline to the inserted text.
}
p' "$FILE" > "$FILE.mod" && mv -f -- "$FILE.mod" "$FILE"
}

命令替换 "$("$3"| sed '...')" 过滤输出$3 用于 sedi 命令。 i 命令打印除了最后一行以外,一系列行都以 \ 结尾。

$ echo three | sed 'i\
> one\
> two
> '
one
two
three

关于Bash/Sed - 多行 sed 操作打印行乱序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42585989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com