【问题标题】:Replacing a field in text file with the result of a system command用系统命令的结果替换文本文件中的字段
【发布时间】:2018-02-09 19:54:16
【问题描述】:

使用 Bash 命令,我想将文本文件每一行的字段 3 替换为以原始字段 3 作为参数的命令的结果。字段是/-delimited。

输入文件:

./REMOTE_PARENT_DIR/0x134000564f:0x4c:0x0/test_runs/testgsi_O1
./REMOTE_PARENT_DIR/0x134000564f:0x4c:0x0/test_runs/testgsi_O2
...

所需的输出文件(不打印字段 1 和 2,字段 3 将是 Unix 命令的结果,打印剩余字段):

/scratch/000011/rin/test_runs/testgsi_O1
/scratch/000011/rin/test_runs/testgsi_O2
...

将字段 3 转换为普通路径组件的命令:

hostx#lfs fid2path /scratch [0x134000564f:0x4c:0x0]
/scratch/000011/rin

也许使用awk 获取相关字段,然后使用命令替换sed 然后吐出新行?

这会打印出我需要的位,但不确定如何替换到文件的行中:

awk -F "/" '{ system("/bin/lfs fid2path /scratch " $3) }' outfile.70.sample.tmp

【问题讨论】:

  • 用简单的循环计算出来,一旦我弄清楚如何将其格式化得体,就会发布。

标签: bash awk sed


【解决方案1】:

以下awk one-liner 将有助于实现您的目标:

awk 'BEGIN { FS="/"; OFS="/" } { cmd = "/bin/lfs fid2path /scratch "$3; cmd | getline path; close(cmd); for (i = 4; i <= NF; i++) { path = path""OFS""$i};print path }' your_input_file.txt
  • 在这里,在读取和处理任何输出之前,我们在 BEGIN 规则中将字段分隔符 FS 和输出字段分隔符 OFS 分配给斜杠 /
  • 然后我们根据您所需的 shell 调用创建一个命令 cmd 变量,并将第三个字段 $3 作为参数。
  • 我们执行cmd shell 命令并将其输出通过管道传递到内置命令getline 并放入变量path
  • 调用 close() 函数以在生成输出后关闭 cmd 并确保命令针对每条记录运行。
  • 然后使用 for 循环,我们将从第 4 个字段开始直到行尾的值连接到以 OFS 分隔的 path 变量。
  • 最后我们打印出所需的更改路径。由于我没有安装/bin/lfs 命令,我只是用cmd = "echo "$3" | cut -d':' -f2" 对其进行了测试以查看结果,它看起来很好。

例如paths.txt:

./REMOTE_PARENT_DIR/0x134000564f:0x4c:0x0/test_runs/testgsi_O1
./REMOTE_PARENT_DIR/0x134000564f:0x4c:0x0/test_runs/testgsi_O2

调用示例:

awk 'BEGIN { FS="/"; OFS="/" } { cmd = "echo "$3" | cut -d':' -f2"; cmd | getline path; close(cmd); for (i = 4; i <= NF; i++) { path = path""OFS""$i};print path }' paths.txt

产生结果:

0x4c/test_runs/testgsi_O1
0x4c/test_runs/testgsi_O2

使用 shell 命令 cut -d':' -f2 从第三个 awk 字段 $3 提取特定部分。即从冒号 (:) 分隔的字符串中的 2nd 字段:0x134000564f:0x4c:0x0

【讨论】:

    【解决方案2】:

    我希望你的问题理解正确,否则告诉我删除这个 请回答。

    如果您不介意使用 Perl,那么您可以非常简单直接地做到这一点

    考虑以下单行

    perl -F'/' -ne '$F[2]="add-some-text/"; print @F[2..$#F]' file 
    

    它逐行读取文件,并将文件 2 替换为 add-some-text,它具有以下输出:

    all-some-text/test_runstestgsi_O1
    all-some-text/test_runstestgsi_O2
    

    现在,如果您想使用命令,只需使用命令而不是简单的文本,但在 Perl 中使用 back-stick 运算符:

    perl -F'/' -ne '$F[2]=`date "+%H:M:S"`; print @F[2..$#F]' file
    

    qx() 更易读:

    perl -F'/' -ne '$F[2]=qx(date "+%H:M:S"); print @F[2..$#F]' file
    

    如果你想传递一个参数,你也可以这样做:

    perl -F'/' -ne '$F[2]=qx(echo -n $F[2]/); print @F[2..$#F]' file  
    

    最终替换只是在-F 之前使用-i.bak。它将创建一个类似file.bak 的备份文件并修改您的原始文件。

    【讨论】:

      【解决方案3】:
      #!/bin/bash
      
      OUTFILE03=tmpfile
      
      while IFS=/ read first second fid remainder
      do
          REAL=`/bin/lfs fid2path /scratch $fid`
          echo "$REAL/$remainder"
      done <"input.70"  >$OUTFILE03
      

      【讨论】:

      • 嗨。您能否简要解释一下这是如何解决原始问题的?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 2015-02-07
      • 1970-01-01
      • 2023-03-26
      • 2015-08-07
      • 2020-08-31
      • 1970-01-01
      相关资源
      最近更新 更多