在bash中

时间:2019-04-11 15:53:45

标签: bash shell sh

假设我有一个文件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中编辑该特定行。

任何其他解决方案或更好的方法也将起作用。

1 个答案:

答案 0 :(得分:0)

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

#! /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 '%s\n' "${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生成了新密码。您可能还想做其他事情。
  • 演示代码中没有错误检查。实际代码应检查丢失的文件,不可读的文件,不可写的文件,函数的参数数量错误等。