【问题标题】:bash script to locate variable and replace string between quotes a few lines belowbash 脚本来定位变量并替换下面几行引号之间的字符串
【发布时间】:2016-07-27 14:18:50
【问题描述】:

我有一个纯文本文件“用户数据库”,其中包含一遍又一遍重复的相同 4 行。每 4 行“数组”代表用户数据库中的一个用户,如下所示:

   'AX112233':  
      uid      => '22044',  
      groups   => ['grp01'],  
      password =>  'passwordXYZ',  
      comment  => 'Mickey Mouse';  

AX112233 始终是唯一值。我需要一个脚本,当给定 2 个值时,即唯一用户名 AX112233 和新密码 AX112233:passwordABC,将能够在文件中找到唯一用户名并替换引号之间的密码值 3 行。

所以在接收到AX112233:passwordABC作为输入后,数组会改变如下:

'AX112233':
      uid      => '22044',  
      groups   => ['grp01'],  
      password =>  'passwordABC',  
      comment  => 'Mickey Mouse';  

最好是用bash/sed/awk/ 写的东西,但不一定是这样。任何帮助将不胜感激。

到目前为止,我所拥有的是这个 Perl 脚本。我确信这对于 Perl 专家来说是一件容易的事,而我不是。脚本的问题是初始密码未知,因此脚本需要替换 password => 之后单引号之间的任何内容

$ cat input.txt 
AX112233':  
      password =>  'passwordXYZ',  
      uid      => '22044',  
      groups   => ['grp01'],  
      comment  => 'Mickey Mouse';  
$ perl -pe '++$x and next if /AX112233/; $x-- and s/passwordXYZ/passwordABC/ if $x' input.txt 
AX112233':  
      password =>  'passwordABC',  
      uid      => '22044',  
      groups   => ['grp01'],  
      comment  => 'Mickey Mouse';

上面的另一个问题是行密码必须是AX11223下面的下一行。如果该行低于 3 行,例如

AX112233':  
      uid      => '22044',  
      groups   => ['grp01'],  
      password =>  'passwordABC',  
      comment  => 'Mickey Mouse';

【问题讨论】:

  • SO 不是免费的编码服务,我们在这里帮助您修复代码。但您必须先尝试,并展示您的尝试,以便我们帮助您了解哪里出了问题。
  • 这应该很简单,使用awk
  • 抱歉,我应该提到我一直在做的事情,认为这对程序员来说很容易。
  • 给一个人一条鱼,他可以吃一天;教他钓鱼,他吃一辈子。我在教你钓鱼,这意味着你必须自己尝试。
  • 此外,显示您目前拥有的代码可以大大缩小我们需要解释的部分。很多时候,问题中的诊断结果需要一个解释基本引用或运算符优先级的答案,而不是 OP 认为的问题。

标签: linux bash perl sed substitution


【解决方案1】:

使用 sed,您可以使用 sed 地址搜索 $username,并将从该地址找到的下一个密码替换为 $newpass 值:

username="AX112233"; 
newpass="passwordABC";
sed "/ *'$username'/,/;/{s/^\([ \t]*password => *'\).*/\1$newpass',/}" file

【讨论】:

    【解决方案2】:

    您的 Perl 脚本的简单改编可以很容易地工作:

    perl -pe '++$x and next if /AX112233/;
              /password\s*=>/ and $x-- and '"s/'[^']*'/'passwordABC'/"' if $x' input.txt
    

    里面有一些贝壳诡计,而不是真正的 Perl 魔法。第一行与您所拥有的相同。第二行查找包含password => 的行,然后使用一些shell 技巧将单引号更改为双引号('",然后包含查找单引号、任意字符序列的s/// 命令不是单引号和另一个单引号,并用单引号括起来的密码的新值替换它。"' 恢复为单引号字符串,因此if $x 不需要反斜杠。有是更简洁的方法,但这是你所拥有的一个简单的变化。

    给定这样的输入文件:

    'AX112233':
          password =>  'passwordXYZ',
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX221133':
          password =>  'passwordXYZ',
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          password =>  'passwordXYZ',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX113322':
          uid      => '22044',
          password =>  'passwordXYZ',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          groups   => ['grp01'],
          password =>  'passwordXYZ',
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse',
          password =>  'passwordXYZ';
    

    (对于不同的用户 ID 有 2 个条目,并且在匹配的用户 ID 之后的第一行、第二行、第三行或第四行有密码)生成:

    'AX112233':
          password =>  'passwordABC',
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX221133':
          password =>  'passwordXYZ',
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          password =>  'passwordABC',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX113322':
          uid      => '22044',
          password =>  'passwordXYZ',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          groups   => ['grp01'],
          password =>  'passwordABC',
          comment  => 'Mickey Mouse';
    'AX112233':
          uid      => '22044',
          groups   => ['grp01'],
          comment  => 'Mickey Mouse',
          password =>  'passwordABC';
    

    另一种方法:

    user="AX112233"
    password="passwordABC"
    
    perl -pe 'if ('"/$user/"') { ++$x; next }
              if ($x && '"s/password\s*=>\s*'[^']*'/password => '$password'/"') { $x-- }' input.txt
    

    这将匹配和替换组合在一个操作而不是两个操作中,并使用常规前导 if 而不是尾随 if 条件。它还允许通过 shell 变量指定用户名和新密码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 2019-10-08
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      • 2014-09-07
      • 1970-01-01
      相关资源
      最近更新 更多