我有一个名为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
我无法理解为什么这不起作用。 任何人都可以解释为什么会这样,并为这个问题提出适当的解决方案吗?
谢谢!
答案 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_
)的开头删除^
,留下数字(或行上的任何其他内容)。根本不需要循环!