【问题标题】:Trying to pull insert values from array in specific file试图从特定文件中的数组中提取插入值
【发布时间】:2021-03-09 21:19:55
【问题描述】:

我的问题是我想在 config.xml 中的特定行上写入 $i 的值,请参见下面的 config.xml 结构。 另外,我希望所有行都在另一行之下,而不是在同一行中。

#!/bin/bash

NAME_ID=( User1 User2 User3 )
USER_CONF=/opt/test/config.xml

for i in "${NAME_ID[@]}"; do
      
  printf '<user><id>ID</id><name><%s/name></user>\n' "$i" >> "$EXTERNAL_USER_CONF"

done

config.xml 结构如下(我想将所有三行插入另一行下方,其中显示 USER_TO_INSER_HERE 但我最终得到它们):

<company type="external">
    <enabled>true</enabled>
    <users type="allowed">
        USER_TO_INSERT_HERE
    </users>
</company>
        <domain><id>ID</id><name><User1/name></domain>
        <domain><id>ID</id><name><User2/name></domain>
        <domain><id>ID</id><name><User3/name></domain>

我期望的最终结果是:

<company type="external">
    <enabled>true</enabled>
    <users type="allowed">
        <domain><id>ID</id><name><User1/name></domain>
        <domain><id>ID</id><name><User2/name></domain>
        <domain><id>ID</id><name><User3/name></domain>
    </users>
</company>

【问题讨论】:

  • on a specific lines 具体是哪几行?要修改 XML 文件,请使用 XML 感知工具,例如 xmlstarlet&lt;company="external"&gt;&lt;users="allowed"&gt; 也是无效的 XML。
  • 谢谢@KamilCuk 刚刚修正了你的建议,你是对的我忽略了 xml,因为我试图专注于我更大的问题。

标签: arrays bash shell writing


【解决方案1】:

以下代码:

tmp=$(cat <<EOF
<company type="external">
    <enabled>true</enabled>
    <users type="allowed">
    </users>
</company>
EOF
)

for i in user1 user2 user3; do
      value=$(printf '<id>ID</id><name>%s</name>\n' "$i")
      tmp=$(xmlstarlet ed -s '/company/users' -t elem -n domain -v "$value" <<<"$tmp")
done

tmp=$(xmlstarlet unesc <<<"$tmp")
cat <<<"$tmp"

在我的电脑上输出xml 1.6.1:

<?xml version="1.0"?>
<company type="external">
  <enabled>true</enabled>
  <users type="allowed">
    <domain><id>ID</id><name>user1</name></domain>
    <domain><id>ID</id><name>user2</name></domain>
    <domain><id>ID</id><name>user3</name></domain>
  </users>
</company>

它基于How do I use xmlstarlet to append xml files with multiple sub node?

【讨论】:

  • 该实现中只有一个流程似乎用户是写在一行中的,我尝试了 addind \n 但在 xmlstarled 中不起作用。你知道我如何在每个之后换行:ID
  • one flow 我想你的意思是一个缺陷。我在每个&lt;/domain&gt; 之后都会收到换行符。与其手动进行,不如使用工具对其进行格式化。就像字面上的xmlstarlet fo。但我建议使用更好的语言来处理 XML。像蟒蛇。
【解决方案2】:

使用纯 bash shell 解决方案,在处理大量数据/文件时会非常/痛苦地缓慢。

file.xml 及其内容。

<company type="external">
    <enabled>true</enabled>
    <users type="allowed">
    </users>
</company>

脚本。

#!/usr/bin/env bash

user_conf=file.xml
name_id=(User{1..10})
line_to_insert_user_below='^([[:blank:]]+)<users="allowed">'

while IFS= read -r line; do
  if [[ $line =~ $line_to_insert_user_below ]]; then
    intended_ouput+=("$line")
    leading_space=${BASH_REMATCH[1]}
    leading_space+=$leading_space
    for i in "${name_id[@]}"; do
      intended_ouput+=(
        "$leading_space<domain><id>ID</id><name><$i</name></domain>"
      )
    done
    continue
  fi
  intended_ouput+=("$line")
done < "$user_conf"

printf '%s\n' "${intended_ouput[@]}" > "$user_conf"

file.xml 的编辑输出

<company="external">
    <enabled>true</enabled>
    <users="allowed">
        <domain><id>ID</id><name><User1/name></domain>
        <domain><id>ID</id><name><User2/name></domain>
        <domain><id>ID</id><name><User3/name></domain>
        <domain><id>ID</id><name><User4/name></domain>
        <domain><id>ID</id><name><User5/name></domain>
        <domain><id>ID</id><name><User6/name></domain>
        <domain><id>ID</id><name><User7/name></domain>
        <domain><id>ID</id><name><User8/name></domain>
        <domain><id>ID</id><name><User9/name></domain>
        <domain><id>ID</id><name><User10/name></domain>
    </users>
</company>    

如另一个答案中所述,使用支持 xml 的工具或具有用于解析和编辑 xml 文件的库的语言。如果您无法访问此类工具且文件不大,则此解决方案只是最后的手段。

【讨论】:

    猜你喜欢
    • 2016-08-18
    • 2021-02-27
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    相关资源
    最近更新 更多