【问题标题】:Replace certain lines and columns with a value of a variable用变量的值替换某些行和列
【发布时间】:2017-12-13 21:01:28
【问题描述】:

我无法找到以下问题的解决方案: 我的文本文件的顶部看起来像这样

XXXXX
XXXXXX XXXXXXX
X
X
X
XX
X
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  XXXXXXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  XXXXXXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  XXXXXXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  XXXXXXE+00

X 是随机数。这种从第 16 行开始的模式(vim 显示为第 16 行)一直持续到文件末尾(根据 vim 为第 71 行)。这些行总是以空格键开头,后跟一个数字,两个数字之间是两个空格键。 我有一个变量 v ,其值例如 v=1.50 我想用变量 v 的值替换从第 16 行到第 71 行的所有行的最后一列的前 4 个 X,这意味着我希望在最后有这个文件(行首的空格应该保留) :

XXXXX
XXXXXX XXXXXXX
X
X
X
XX
X
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00

我用 awk 试了一下,但我遇到的问题是它在数字之间添加了空格(如 1 . 5 0 ),而且我无法将它粘贴到正确的列和行中(vim 显示“二进制”列)我找不到正确的 awk 列。 我该怎么做?我想使用脚本对许多文件执行此操作。 非常感谢您的帮助!

【问题讨论】:

  • :%s/X\{6}E+00$/1.50XXE+00 不起作用有什么原因吗?还是你想让它使用一些变量?
  • 嗨,是的,1.50 只是一个例子。我也有很多文件,所以我不能为每个文件输入 vim 并且想从每个文件的 bash 脚本中自动完成。而且我忘了写X是随机的不同数字,所以我不知道前面是什么。
  • 当你说你有一个变量,你是什么意思?一个shell变量?某个程序中的变量?它的数据类型是什么?
  • wrt I tried a bit with awk, but I had the problem that it adds spaces between the numbers (like 1 . 5 0 ) - 我无法想象你写了什么 awk 代码来做到这一点,但如果你想帮助调试它,然后发布它。

标签: vim awk


【解决方案1】:

这里sed 可能是更好的选择

$ var="1.50"; sed -E '8,$s/ ....(\S+)$/ '"$var"'\1/' file

XXXXX
XXXXXX XXXXXXX
X
X
X
XX
X
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00 1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00 1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00 1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00 1.50XXE+00

在您的示例中,替换行从第 8 行开始。根据您的实际数据进行更改。

您也可以将变量的长度作为派生值

$ var="1.50"; len=${#var}; sed -E '8,$s/ .{'$len'}(\S+)$/  '$var'\1/' file

【讨论】:

  • 嗨,谢谢,看起来不错!如果我有一个值为 v=1.50 的变量,我是否只需要使用 "sed -E '8,$s/(.*) ....(\S+)$/\1$v\2/'文件”而不是?
  • 检查更新版本。要在脚本中插入 $v,您必须将单引号更改为双引号。
  • 谢谢,这正是我想要的。还有两件事:我尝试使用 sed -i 而不是 -E 直接将更改写入文件,但这似乎不起作用?如果文件的名称为“adffa.d23-24_3334_+4.33_-3.42_-5555_1.50.pfadf”,我可以使用哪个 bash 命令提取 1.50(或文件结尾前的最后 4 个字符)并保存变成一个变量?
  • 您需要保留-E 以供正则表达式组参考。您还可以拥有-i。为了从文件名中提取值,请发布一个新问题。
【解决方案2】:

只是为了简单、清晰、健壮、可移植、可扩展等而使用 awk...:

awk -v v='1.50' 'BEGIN{FS=OFS="  "} NR>15{sub(/.{4}/,v,$NF)} 1' file

例如使用您发布的示例输入:

$ awk -v v='1.50' 'BEGIN{FS=OFS="  "} NR>7{sub(/.{4}/,v,$NF)} 1' file
XXXXX
XXXXXX XXXXXXX
X
X
X
XX
X
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00
 XXXXXXE+00  XXXXXXEE+03  XXXXXXE+07  XXXXXXE+00  1.50XXE+00

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-27
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多