我需要脚本将此假期列表转换为日期格式。我的输入文件
MMYYYY CAL_B2K_ID 123456789012345678901234567890
------ ------------ -------------------------------
012016 821 YY Y Y Y Y
012016 DC YY Y Y Y Y
022016 DC Y Y Y Y
022016 821 Y Y Y Y
032016 DC Y Y Y Y
032016 821 Y Y Y Y
042016 821 Y Y Y Y
现在 123456789012345678901234567890 就像日期,第一次出现 0 时它是 10,然后 1 表示 11,如此类推。 ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14............
所以我创建了脚本,其中存在 Y 的地方都会转换为日期,假设第一行 Y 出现在 1, 2,9,6,3,9 下
在我的脚本中,我从第 21-52 列中删除了每一行,并检查该列是否为 Y,如果是,则它会隐藏为日期,就像 Y 出现在第 23 列下一样。然后我进行减法(列号 - 20),它将给我 3 然后我使用 concat 运算符来制作日期。
下面是我的脚本。但我面临的问题是,当任何列下都没有 Y 时,它会将我的 var 作为空白,并且空白也在真实条件下出现。
var=echo $f1 | cut -c$i
if [[ "$var"='Y' ]] ;
我的脚本如下。
rm f1.txt
set -x
while read f1
do
for((i=21;i<23;i++));
do
var=`echo $f1 | cut -c$i`
if [[ "$var"='Y' ]] ;
then
echo $var
month=`echo $f1 | cut -c1-2`
year=`echo $f1 |cut -c3-6`
date=$(($i-20))
echo $year"-"$month"-"$date >> f1.txt
fi
done
done < holiday_india.txt`
请让我知道我将做什么,以便当 var 中没有任何内容时,它不会出现在 If 条件 true 下。
该脚本的 O/p 是将每行从 21-52 的所有列转换为日期,而不是 Y 所在的位置。
希望我现在澄清一下。
答案1
好的,我复制了下面的脚本,并修复了缩进,以便我更容易阅读。 (我还更改了反引号$()
并删除了固定文件名,因为我喜欢这样。)
while read f1 ; do
for((i=21;i<23;i++)); do
var=$(echo $f1 | cut -c$i)
if [[ "$var"='Y' ]] ; then
echo $var
month=$(echo $f1 | cut -c1-2)
year=$(echo $f1 |cut -c3-6)
date=$(($i-20))
echo "$year-$month-$date"
fi
done
done
有两件事跳了起来:
if [[ "$var"='Y' ]] ; then
这是行不通的;等号周围需要空格。尝试看看[[ X=Y ]] && echo foo
会发生什么。
也在这里
var=$(echo $f1 | cut -c$i)
f1
包含类似 的内容012016 821 YY Y Y Y Y
,但由于它没有被引用,所以它会被扩展,然后沿着空格进行单词分割,然后echo
打印由 分隔的所有单词单身的空格,导致012016 821 YY Y Y Y Y
.您可以通过添加引号来修复它:echo "$f1" | cut -c$i
,但也可以获取长度的子字符串"${f1:N:L}"
L从位置氮。但它是零索引的,因此$i
需要修改的范围。
然后,
echo "$year-$month-$date"
可以将其更改为,printf "%04d-%02d-%02d\n" "$year" "$month" "$date"
以确保日期始终以两位数打印,并防止出现可能的异常值$year
。
不妨将月份和年份分配移到外循环,因为它们在整行中保持不变。
现在我们有:
while read f1; do
month="${f1:0:2}"
year="${f1:2:4}"
for (( i=20 ; i < 20 + 31 ; i++ )); do
var="${f1:$i:1}"
if [[ "$var" = "Y" ]] ; then
date=$(( $i - 19 ))
printf "%04d-%02d-%02d\n" "$year" "$month" "$date"
fi
done
done
当我运行它时,输出看起来是正确的bash holiday.sh < holiday_india.txt
:
2016-01-01
2016-01-02
2016-01-09
2016-01-16
2016-01-23
2016-01-30
2016-01-01
︙
当然,你似乎所有月份都加倍了,所以它们的产出也加倍了。也许添加对第二列内容的测试,或者使用类似这样的内容运行它以仅检查具有给定 id 的行:
grep DC holiday_india.txt | bash holiday.sh
(这当然也会跳过标题行。或者您可以检查行开头的月份/年份是否正常。)
这是用 ksh 标记的,但我使用的是 bash。ksh
I have support的副本,我认为这是我使用的唯一新语法。${foo:N:L}