我正在编写自己的密码管理器,我希望它严格符合 POSIX 标准。为了简化:我有这个文件file.csv
:
mastodon;password2
bla;test
test;test
posteo;tewtasdwqrr
基本上,我想要一个带有两个参数的函数:它应该从第一列中选择第一个参数,并从该行中,它应该用第二个参数替换第二列条目。
例如:f "bla" "etewtw"
将最后一个条目的密码更改为etewtw
。
我尝试使用 awk,它也有一定的作用:
awk -F ";" -v acc="bla" -v newpw="etewtw" \
'$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} ' file.csv
newpw
基本上,如果第一列与参数匹配,我尝试将第二列设置为参数acc
。更改流后,我想打印完整的流,但不起作用。上面显然不是正确的解决方案,但我不知道如何解决这个问题。
输出是:
bla;etewtw
posteo;tewtasdwqrr
所以它有点成功,条目被更改(至少在流中,但实际上更改文件并不困难)。
然而,出现了两个问题:
输出中缺少条目。即
mastodon;password2
和test;test
。我希望它们a)保持在同一条线上,b)保持不变。如果我想改变最后一行,它总是错误的。例如,如果我使用
awk -F ";" -v acc="posteo" -v newpw="test" '$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} '
它,结果是:
posteo;test
posteo test
这不是我想要的。我希望最后一行与其他行没有什么不同。
答案1
您需要其中任何一个才能将您的名称和密码视为文字字符串:
acc='bla' newpw='etewtw' awk '
BEGIN{FS=OFS=";"; acc=ENVIRON["acc"]; newpw=ENVIRON["newpw"]}
$1 == acc{$2=newpw} 1
' file.csv
awk '
BEGIN{FS=OFS=";"; acc=ARGV[1]; newpw=ARGV[2]; ARGV[1]=ARGV[2]=""}
$1 == acc{$2=newpw} 1
' 'bla' 'etewtw' file.csv
您需要这种方法,因为变量是通过-v
扩展转义序列传递的。因此,如果您传递的任何一个变量包含反斜杠,例如foo\tbar
,那么\t
中间的 将会被扩展并被视为文字制表符。
看http://cfajohnson.com/shell/cus-faq-2.html#Q24和/或https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script了解更多信息。
答案2
我认为唯一必要的修改是您print
在该END
部分中有一个声明,但缺少一个不匹配行的声明。相反你应该做的是
awk -F';' -v OFS=';' -v acc='bla' -v newpw='etewtw' '$1 == acc {$2=newpw}1' file.csv
即只需替换字段 Nr。 2 使用新密码,并通常打印(可能修改过的)行(其简写符号是1
)。这样我也成功改变了最后一行的记录。
另外,让您的条件精确匹配而不是正则表达式似乎是明智的,您永远不知道一个帐户名称是否可能包含与另一个帐户名称匹配的字符串(如 和 中的字符串admin
,webadmin
例如)。