저는 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
).