在 bash 中读取文件并同时(逐行)编辑文件



假设我有一个文件temp.yaml

# Comment shouldn't be deleted
passwords:
    key1: __password__
    key2: __password__
    key3: __password2__
    key4: __password__
# All comments should be preserved
passwords-new:
    key1: __newPassword__

在此文件中,我希望每个__password__字段具有不同的值。本质上,此文件中的所有密码都具有不同的值。

我想逐行读取文件并用新生成的密码存储/替换密码。但不确定,我如何逐行浏览文件并同时在 bash 中编辑该特定行。

任何其他解决方案或更好的方法也将奏效。

如果 YAML 文件不是太大,则可以使用 Bash 代码在内存中进行编辑并将结果写回文件。 这个,Shellcheck-clean,代码演示了这个想法:

#! /bin/bash -p
# Set passwords in a YAML file.  Update the file in place.
function set_yaml_passwords
{
    local -r yaml_file=$1
    # Create a regular expression to match key/password lines
    local -r key_rx='^([[:space:]]*key[[:digit:]]*:[[:space:]]*)'
    local -r pw_rx='__[[:alnum:]]*[Pp]assword[[:alnum:]]*__[[:space:]]*$'
    local -r key_pw_rx=${key_rx}${pw_rx}
    # Read the YAML file lines into an array, setting passwords as we go
    local yaml_lines=() is_updated=0
    local line keystring newpw
    while IFS= read -r line || [[ -n $line ]] ; do
        if [[ $line =~ $key_pw_rx ]] ; then
            keystring=${BASH_REMATCH[1]}
            newpw=$(pwgen 10)
            yaml_lines+=( "${keystring}${newpw}" )
            is_updated=1
        else
            yaml_lines+=( "$line" )
        fi
    done <"$yaml_file"
    # If any passwords have been set, update the YAML file
    if (( is_updated )) ; then
        printf '%sn' "${yaml_lines[@]}" >"$yaml_file"
        printf "Updated '%s'\n" "$yaml_file" >&2
    fi
    return 0
}
set_yaml_passwords 'temp.yaml'

这是通过在问题中给出的示例 YAML 文件上运行上述代码生成的 YAML 文件的示例:

# Comment shouldn't be deleted
passwords:
    key1: yai9cegiD4
    key2: Ahtah1eyoh
    key3: ya1teo1ooB
    key4: AhGae5EiLe
# All comments should be preserved
passwords-new:
    key1: oaKoh0teiK
  • Bash 代码中的逐行处理非常慢。 上面的代码花了将近 1 秒的时间在我的(旧(Linux 系统上处理一万行文件(带有少量的密钥/密码行(。 在现代系统上,您会在遇到内存问题之前很久就遇到时间问题。
  • 我使用pwgen 10来生成新密码。 你可能想做点别的事情。
  • 演示代码中没有错误检查。 实际代码应检查丢失的文件、不可读的文件、不可写的文件、函数参数数量错误等。

最新更新