简体   繁体   English

MacOS SED 找到第二个匹配行并在其上方插入行

[英]MacOS SED to find a second matching line and insert lines above it

I am looking for a BASH sed script that can open an .mdx file and search line by line and find the second line that has the value I'm searching for: three hyphens like this --- .我正在寻找一个 BASH sed 脚本,该脚本可以打开一个.mdx文件并逐行搜索并找到具有我正在搜索的值的第二行:三个连字符像这样--- Then, I'm hoping to insert two lines of redirect information above that second set of hyphens.然后,我希望在第二组连字符上方插入两行重定向信息。

The second occurrence of these three hyphens could be on any line following line 1, so I would need a script that is smart enough to search until it finds the second one.这三个连字符的第二次出现可以在第 1 行之后的任何行上,所以我需要一个足够聪明的脚本来搜索,直到找到第二个。

I'll need something that runs in the MacOS that can do some in-place file updates.我需要在 MacOS 中运行的可以进行一些就地文件更新的东西。

Here's my input file:这是我的输入文件:

---
title: Some kind of title
---

I'd like to locate that second instance of three hyphens and insert new text above it like this:我想找到三个连字符的第二个实例并在其上方插入新文本,如下所示:

---
title: Some kind of title
redirects:
  - /some/kind/of/directory/path
---

In my shell script, I have a variable that contains that redirect path, so I would somehow need to pass that variable along with a hard-coded redirects: to sed.在我的 shell 脚本中,我有一个包含该重定向路径的变量,因此我需要以某种方式将该变量与硬编码的redirects:到 sed。

I looked at a variety of options, including the POSIX option included here , but it just deletes the second occurrence.我查看了各种选项,包括此处包含的 POSIX 选项,但它只是删除了第二次出现。 Perhaps there's an easy way I could modify that to update?也许有一种简单的方法可以修改它以进行更新?

Let me know if you need more to understand what I'm looking for.如果您需要更多了解我在寻找什么,请告诉我。

This is one way of doing it:这是一种方法:

testpath="/some/kind/of/directory/path"
sed "s|---|redirects:\n\ \ -\ $testpath\n---|" file.mdx | sed '/---/,$!d'

This works by adding the "redirect: path" directly above both "---" lines, then deletes the top "redirect: path".这可以通过在两个“---”行上方直接添加“redirect:path”,然后删除顶部的“redirect:path”来实现。 This will fail miserably if there is more than two "---" in the file.如果文件中有两个以上的“---”,这将失败。

To do it inline:内联:

testpath="/some/kind/of/directory/path"
sed -i .bak "s|---|redirects:\n\ \ -\ $testpath\n---|" test.txt && sed -i _bak2 '/---/,$!d' test.txt

You can find out the line number of the 2nd --- and then insert before that line.您可以找出第二个---的行号,然后在该行之前插入。

Example (tested on macos):示例(在 macos 上测试):

$ cat file
---
title: Some kind of title
---
$ cat foo.sh
path=/some/kind/of/directory/path
n=$( sed -n '/^---$/=' file | sed -n 2p )
sed -e "$n i\\
redirects:\\
 - $path
" file
$ bash foo.sh
---
title: Some kind of title
redirects:
 - /some/kind/of/directory/path
---
$

(Use sed -i for updating the file in place.) (使用sed -i更新文件。)

Are you hellbent on using sed for this?您是否愿意为此使用sed Generally Awk is both more versatile and more readable.通常 Awk 更通用,更易读。

awk '/^---$/ { print; hyphens=1; next }
    hyphens && /^title: / { print; print "redirects:\n  - /some/kind/of/directory/path"; next }
    { hyphens=0 } 1' file.mdx >newfile.mdx

In brief, we keep track of whether the previous line was three hyphens;简而言之,我们跟踪前一行是否是三个连字符; if it was, and the current line matches the regex ^title: , print the additional lines.如果是,并且当前行与正则表达式匹配^title: ,则打印附加行。 Otherwise, we reset the state variable and print.否则,我们重置 state 变量并打印。 (The final 1 is a common Awk idiom to avoid having to say { print } explicitly.) (最后的1是一个常见的 Awk 成语,以避免必须明确地说{ print } 。)

Unfortunately, standard Awk has no -i option.不幸的是,标准 Awk 没有-i选项。 If you can use GNU Awk, it has an option -i inplace which emulates the (also nonstandard, but common) -i option of sed .如果您可以使用 GNU Awk,它有一个选项-i inplace模拟sed的(也是非标准但常见的) -i选项。 Otherwise, just write to a temporary file and move it back onto the original afterwards;否则,只需写入一个临时文件,然后将其移回原始文件; that's what -i does behind the scenes, too.这也是-i在幕后所做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM