带有变量

时间:2016-03-20 23:10:36

标签: bash for-loop sed

我有一个名为dates.txt的文件,其中包含以下内容:

DATE_1
DATE_2
DATE_3
DATE_4
DATE_5
DATE_6
DATE_7

我只想用一些使用sed命令存储在v array中的日期替换DATE_i。 为此,我尝试了for循环和sed命令(文件test.sh):

#!/bin/bash
v[1]=`date -d "7 days ago" '+%d\/%m\/%y'`
v[2]=`date -d "6 days ago" '+%d\/%m\/%y'`
v[3]=`date -d "5 days ago" '+%d\/%m\/%y'`
v[4]=`date -d "4 days ago" '+%d\/%m\/%y'`
v[5]=`date -d "3 days ago" '+%d\/%m\/%y'`
v[6]=`date -d "2 days ago" '+%d\/%m\/%y'`
v[7]=`date -d "1 days ago" '+%d\/%m\/%y'`

cat dates.txt|for j in {1..7};do sed "s/DATE_$j/${v[$j]}/";done

问题是此命令仅替换第一个日期。如果你运行test.sh:

$ ./test.sh 
14/03/16
DATE_2
DATE_3
DATE_4
DATE_5
DATE_6
DATE_7

我期待的输出是:

14/03/16
15/03/16
16/03/16
17/03/16
18/03/16
19/03/16
20/03/16

我无法理解为什么这不起作用。 任何人都可以解释为什么会这样,并为这个问题提出适当的解决方案吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

说明:正在发生的事情是for循环的第一次迭代正在消耗您为其标准输入提供管道的所有行。首先,让我们修改test.sh以在最后一行中包含echo语句,以便我们可以看到发生了什么:

cat dates.txt|for j in {1..7};do echo $j; sed "s/DATE_$j/${v[$j]}/";done

您会看到test.sh的输出如下:

1
13/03/16
DATE_2
DATE_3
DATE_4
DATE_5
DATE_6
DATE_7
2
3
4
5
6
7

接下来,将dates.txt修改为:

DATE_1
DATE_2
DATE_1
DATE_4
DATE_1
DATE_6
DATE_1

,我们已将所有其他行转换为DATE_1以进行演示。现在,输出显示:

1
13/03/16
DATE_2
13/03/16
DATE_4
13/03/16
DATE_6
13/03/16
2
3
4
5
6
7

所以你看到for循环的第一次迭代(当$j == 1)正在处理cat传递给for循环的每一行。之后,for循环($j == 2..7)的后续迭代仍在运行,但它们不会接收任何输入流(因此,在上面的示例中,它们只是echo $j的当前值,并且不会将任何输入传递给sed)。这就是为什么你观察它只改变第一行的原因。

解决方案:修改最后一行:

for j in {1..7}; do head -$j dates.txt | tail -1 | sed "s/DATE_$j/${v[$j]}/"; done

答案 1 :(得分:0)

cat dates.txt | sed 's/^DATE_//g'

这将在一行(DATE_)的开头删除^,留下数字(或行上的任何其他内容)。根本不需要循环!