我正在尝试编写一个 Shell 脚本来编辑输入文件。输入文件中的数据结构如下:
1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
正如第一行所强调的那样,使用空格进行对齐。我目前正在使用sed
替换参数(每行的第一个“单词”)。
我找不到一种方法可以在不弄乱标签对齐的情况下做到这一点。我愿意接受任何建议,我并不是特别想通过sed
.例如,可以使用选项卡来更改输入文件的结构。
这是我希望脚本执行的操作的示例:
input file
----------
1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
running the script
------------------
$ script --final-time=100
input file after running the script
-----------------------------------
100␣␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
替换字符串的长度事先是未知的。它不固定,最多可包含 6 个字符。
答案1
请改用awk
并将字段格式设置为正确的宽度sprintf()
。这很可能比使用 更直接sed
。
$ cat file
1000 : final time
1000 : print time
0.1 : time step
$ awk -F ':' -v sect=' final time' -v val='100' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
100 : final time
1000 : print time
0.1 : time step
这将处理由 - 分隔字段组成的输入行:
。当第二个字段对应于命令行sect
上赋予变量的字符串时,第一个字段将替换为命令行上awk
赋予的值。val
这里使用的方式sprintf()
,格式字符串为%-16s
,确保您在:
.
使用相同的命令设置“时间步长”只需要插入sect
和 的其他值val
:
$ awk -F ':' -v sect=' time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
1000 : final time
1000 : print time
0.12121212 : time step
值开头的空格sect
需要考虑 后数据中的空间:
。你也可以这样做
$ awk -F ':' -v sect='time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == " " sect { $1 = sprintf("%-16s", val) }; 1' file
1000 : final time
1000 : print time
0.12121212 : time step
(我将值中的空格移至sect
针对第二列值的测试中。)
脚本建议(使用输入文件的静态文件路径,这只是输出修改后的数据):
#!/bin/sh
filepath=some/file/path
if [ "$#" -ne 2 ]; then
echo expecting two arguments >&2
exit 1
fi
case $1 in
--final-time) sect='final time' ;;
--print-time) sect='print time' ;;
--time-step) sect='time step' ;;
*)
printf 'Unknown argument: %s\n' "$1" >&2
exit 1
esac
val=$2
awk -F ':' -v sect="$sect" -v val="$val" '
BEGIN { OFS=FS }
$2 == " " sect { $1 = sprintf("%-16s", val) }; 1' "$filepath"
答案2
一点sed
魔法
v=100; l=${#v}; sed -E "/final/s/[0-9.]/ /g; s/^[ ]{"$l"}/"$v"/" file
由于我们正在寻找,因此我们将其作为匹配的先决条件,然后用以下final
命令删除所有数字和小数:[0-9.]
sed -E "/final/s/[0-9.]/ /g;
编写 的后半部分sed
以替换前一个{$l}
空格,$v
其中$l
只是 的长度$v
s/^[ ]{"$l"}/"$v"/"
任务完成。