如何在Shell脚本中的特定单词之后替换下一个匹配单词

时间:2021-07-16 06:16:33

标签: awk sed grep

我有一个 xml 文件,其中有一行包含多次出现的单词。现在我的目标是在找到匹配项后替换第一次出现。例如下面是文件的示例内容:

我想找到 ticket1 并且只想用 Shyam 替换第一次出现的 Ram_Shyam。

{"body": {"storage": {"representation": "storage", "value":
"<table><tbody><tr><th>Sprint</th><th>Story Id</th><th>Summary</th><th>Team Name</th><th colspan=\"1\">Owner</th><th>Code Check-In</th><th colspan=\"1\">Released Story ID</th><th>Released Status</th><th>Story Closed Date</th><th colspan=\"1\">label</th></tr>
<tr><td colspan=\"10\">NEXT</td></tr><tr><td>Sprint 01</td><td><a href=\"https://jira.com/browse/ticket1\">ticket1</a></td><td>summary</td><td>ABC</td><td>Ram_Shyam</td><td>Yes</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Released</td><td>2021-06-16</td><td>None</td></tr><tr><td>Sprint 74</td><td><a href=\"https://jira.com/browse/ticket2\">ticket2</a></td><td>Summary</td><td>ABC</td><td>Ram_Shyam</td><td>No</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Not Released</td><td>2021-06-16</td><td>None</td></tr>
<tr><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td></tr>
</tbody></table>"
}},"space": {"key": "xyz"}, "title": "Releases Tracker","version": {"number": page_version}, "type": "page"}

有人可以指导如何实现吗?

2 个答案:

答案 0 :(得分:1)

首先,这个问题组织得不好:

  1. 您作为示例提供的“xml”文件似乎是 JSON 对象的一部分,第一部分是 HTML。

  2. “find ticket1”没有明确定义;我们必须猜出你的意思。

  3. “只用...替换第一次出现的...”也不清楚。可以推断您的意思是“在'find ticket1'之后第一次出现”,但这也是一个假设

即便如此,我们还是可以对问题的意图做出一些猜测。

让我们将 HTML 内容放入一个文件中,以便我们可以在后面的命令中使用它。我将其命名为 file.html,我们还将使用 shell 变量 $file 来引用它。

cat <<HTML >file.html
<table><tbody><tr><th>Sprint</th><th>Story Id</th><th>Summary</th><th>Team Name</th><th colspan=\"1\">Owner</th><th>Code Check-In</th><th colspan=\"1\">Released Story ID</th><th>Released Status</th><th>Story Closed Date</th><th colspan=\"1\">label</th></tr>
<tr><td colspan=\"10\">NEXT</td></tr><tr><td>Sprint 01</td><td><a href=\"https://jira.com/browse/ticket1\">ticket1</a></td><td>summary</td><td>ABC</td><td>Ram_Shyam</td><td>Yes</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Released</td><td>2021-06-16</td><td>None</td></tr><tr><td>Sprint 74</td><td><a href=\"https://jira.com/browse/ticket2\">ticket2</a></td><td>Summary</td><td>ABC</td><td>Ram_Shyam</td><td>No</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Not Released</td><td>2021-06-16</td><td>None</td></tr>
<tr><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td></tr>
</tbody></table>
HTML
file=file.html

如果可以简单地将“Ram_Shyam”替换为“Shyam”,则此 sed 命令将起作用:

sed -Ee 's/Ram_Shyam/Shyam/' <$file

如果你运行上面的命令,输出也将是一个难以阅读的 HTML 文本流。

为了更容易阅读,请在 STDIN 或给定文件上使用 tidy 命令,如下所示:

tidy -iq --show-errors 0 $file
<!DOCTYPE html>
<html>
<head>
  ... # rest of of output omitted
</body>
</html>

让我们做一个小别名,让文件的显示更容易:

alias htidy='tidy -iq --show-errors 0'

现在我们只需输入 htidy file.html 即可查看漂亮的 HTML 输出。

这是上面的 sed 输出整理:

sed -Ee 's/Ram_Shyam/Shyam/' <$file | htidy

我们还可以使用 sed 在到达特定行后应用更改。但是,这要求输入是面向行的。因此,以下 sed 命令将应用于管道中 htidy 的输出:

以下 sed 命令将替换 $target 字符串第一次出现后的前 4 行中第一次出现的 $trigger 字符串。

trigger='jira\.com\/browse\/ticket1'
target='Ram_Shyam'
replacement='Shyam'

htidy $file | sed -Ee "/$trigger/,+4s/$target/$replacement/"

如果 target 字符串可能是更大字符串的一部分,例如:"WolfRam",那么我们需要在目标字符串周围放置分词符,如下所示:

trigger='jira\.com\/browse\/ticket1'
target='[[:<:]]Ram_Shyam[[:>:]]'  # see `man re_format`
replacement='Shyam'

htidy $file | sed -Ee "/$trigger/,+4s/$target/$replacement/"

答案 1 :(得分:1)

使用 GNU awk 将第三个参数设置为 match()

$ awk 'match($0,/(.*)(ticket1.*)/,a) { sub(/Ram_Shyam/,"Shyam",a[2]); $0=a[1] a[2] } 1' file
{"body": {"storage": {"representation": "storage", "value":
"<table><tbody><tr><th>Sprint</th><th>Story Id</th><th>Summary</th><th>Team Name</th><th colspan=\"1\">Owner</th><th>Code Check-In</th><th colspan=\"1\">Released Story ID</th><th>Released Status</th><th>Story Closed Date</th><th colspan=\"1\">label</th></tr>
<tr><td colspan=\"10\">NEXT</td></tr><tr><td>Sprint 01</td><td><a href=\"https://jira.com/browse/ticket1\">ticket1</a></td><td>summary</td><td>ABC</td><td>Shyam</td><td>Yes</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Released</td><td>2021-06-16</td><td>None</td></tr><tr><td>Sprint 74</td><td><a href=\"https://jira.com/browse/ticket2\">ticket2</a></td><td>Summary</td><td>ABC</td><td>Ram_Shyam</td><td>No</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Not Released</td><td>2021-06-16</td><td>None</td></tr>
<tr><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td></tr>
</tbody></table>"
}},"space": {"key": "xyz"}, "title": "Releases Tracker","version": {"number": page_version}, "type": "page"}

或任何 awk:

$ awk 'match($0,/ticket1.*/) { tgt=substr($0,RSTART,RLENGTH); sub(/Ram_Shyam/,"Shyam",tgt); $0=substr($0,1,RSTART-1) tgt } 1' file
{"body": {"storage": {"representation": "storage", "value":
"<table><tbody><tr><th>Sprint</th><th>Story Id</th><th>Summary</th><th>Team Name</th><th colspan=\"1\">Owner</th><th>Code Check-In</th><th colspan=\"1\">Released Story ID</th><th>Released Status</th><th>Story Closed Date</th><th colspan=\"1\">label</th></tr>
<tr><td colspan=\"10\">NEXT</td></tr><tr><td>Sprint 01</td><td><a href=\"https://jira.com/browse/ticket1\">ticket1</a></td><td>summary</td><td>ABC</td><td>Shyam</td><td>Yes</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Released</td><td>2021-06-16</td><td>None</td></tr><tr><td>Sprint 74</td><td><a href=\"https://jira.com/browse/ticket2\">ticket2</a></td><td>Summary</td><td>ABC</td><td>Ram_Shyam</td><td>No</td><td><a href=\"https://jira.com/browse/NA\">NA</a></td><td>Not Released</td><td>2021-06-16</td><td>None</td></tr>
<tr><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td><td>Dummy</td></tr>
</tbody></table>"
}},"space": {"key": "xyz"}, "title": "Releases Tracker","version": {"number": page_version}, "type": "page"}
相关问题