使用bash shell脚本替换文件中的字符串

时间:2015-01-18 15:12:50

标签: bash shell scripting

我想在文件中找到一个字符串,做一些操作并将字符串放回文件中。以下是我需要的例子:

$ cat sample.txt
TimeStamp-> 123456 Name-> ABC Mail-> abc@123.com
TimeStamp-> 23456 Name-> XYZ Age-> 25

我来修改我的问题。我想在TimeStamp->之后读取该字符串/数字,根据要求修改相同的字符串/数字并将其放回到相同的文件中或创建新文件。假设操作乘以-1。

预期输出为:

TimeStamp-> -123456 Name-> ABC Mail-> abc@123.com
TimeStamp-> -23456 Name-> XYZ Age-> 25

4 个答案:

答案 0 :(得分:2)

这是一个纯粹的bash解决方案:

while read -ra line; do # read each line in the array "line"
    ((line[1]*=-1))     # multiply the second element (the number) by -1.
    echo "${line[*]}"   # echo the modified line into newfile.txt
done < sample.txt > newfile.txt

解释

while循环read每行array

read选项:

  

-r
      如果给出此选项,则反斜杠不会充当转义字符。反斜杠被认为是该行的一部分。特别是,反斜杠 - 换行符对不能用作续行。

     

-a aname
      这些单词被分配给数组变量aname的顺序索引,从0开始。所有元素在赋值之前从aname中删除。其他名称参数将被忽略。

然后使用Shell Arithmetic*=)将数字(算术表达式)和echo&#39;经过修改的行相乘<强> newfile.txt

答案 1 :(得分:0)

你对问题的心理模型似乎相当不充分。有许多方法可以将文件转换为另一个文件,因此传统方法是通过各种方式生成新文件,然后将其移动到原始文件之上。但为简单起见,您可以使用明确支持就地编辑的工具,例如Perl。

perl -pi~ -e 's/(TimeStamp->\s*)(\d+)/ sprintf("%s%s", $1, -1*$2) /gx' file

这是一个带有s/from/to/选项的正则表达式替换/x,允许替换由另一个Perl表达式生成,而不仅仅是一个字符串。编写简单的日期转换调用而不是sprintf占位符并不困难。正则表达式将静态字符串TimeStamp->和任何尾随空格捕获到$1,将数字捕获到$2

更为“愚蠢”的解决方案是提取数字,在其上运行工具或流程,并单独替换字符串。假设您有一个支持sed选项的i和一个名为ssboetod的工具来计算替换值,可能类似

timestamp=$(sed -n '/.*TimeStamp-> */!d;s///;s/ .*//' file)
converted=$(ssboetod "$timestamp")
sed -i "s/TimeStamp-> *$timestamp/TimeStamp-> $converted/" file

虽然有两个流程替换,但这并不是特别优雅。我将此添加为典型方法的说明,而非实际答案。

最后,如果输入文件格式在您的控制之下,我建议您重新设计。这看起来有点像记录数据,因此半标准的日志文件格式可能更有意义。另一方面,标记字段建议考虑为此数据切换到JSON,尽管这不会简化对此特定问题的处理。

答案 2 :(得分:0)

如果您的文件中有一定数量的列,并且您知道您希望通过算术操作的数字位于第2列,就像您的样本中那样,那么您可以使用awk

awk '{print $1,$2*-1,$3,$4,$5,$6}' file > newFile

注意我将第2列$2乘以-1

newFile应包含:

TimeStamp-> -123456 Name-> ABC Mail-> abc@123.com
TimeStamp-> -23456 Name-> XYZ Age-> 25

答案 3 :(得分:0)

感谢所有帮助。它适用于while循环和sed -i。代码如下:

awk '{print $2}' sample.txt |
while read line
do
    timestamp=$(echo $line |awk '{print $1}')
    converted=$(echo $line |awk '{print $1*-1}')
    sed -i "s/TimeStamp-> $timestamp/TimeStamp-> $converted/" sample.txt
done

在:

cat sample.txt
TimeStamp-> 123456 Name-> ABC Mail-> abc@123.com
TimeStamp-> 12345 Name-> XYZ Age-> 25

后:

cat sample.txt
TimeStamp-> -123456 Name-> ABC Mail-> abc@123.com
TimeStamp-> -12345 Name-> XYZ Age-> 25