この休日リストを日付形式に変換するスクリプトが必要です。入力ファイル
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 の下に存在する場合のように、Y を日付に変換します。次に、(列番号 - 20) を減算すると、3 になります。次に、連結演算子を使用して日付を作成します。
以下は私のスクリプトです。ただし、どの列にも Y がない場合、var が空白として扱われ、true の条件でも空白になるという問題が発生しています。
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 にならないようにするにはどうすればよいか教えてください。
このスクリプトの目的は、Y が存在する場所ではなく、21 から 52 までの各行のすべての列を日付に変換することです。
これで明確になったと思います。
答え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
2 つのことが浮かび上がります。
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}"
ら位置からいいえただし、インデックスはゼロなので、 の範囲$i
を変更する必要があります。
それから、
echo "$year-$month-$date"
これを に変更すると、printf "%04d-%02d-%02d\n" "$year" "$month" "$date"
日付が常に 2 桁で印刷され、 の異常な値から保護されます$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
︙
もちろん、すべての月が 2 倍になっているようですので、出力でも 2 倍になっています。2 番目の列の内容のテストを追加するか、次のように実行して、指定された ID の行のみをチェックしてください。
grep DC holiday_india.txt | bash holiday.sh
(もちろん、これによりヘッダー行もスキップされます。または、行の先頭で月/年が適切であることを確認することもできます。)
これは ksh でタグ付けされていますが、私は bash を使用しました。ksh
私が持っている のコピーは をサポートしており、これが私が使用した唯一の新しい構文だと思います。${foo:N:L}