Мне нужен скрипт для преобразования этого списка праздников в формат даты. Мой входной файл
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 ни под одним столбцом, он принимает мою переменную как пустую, а пустая также попадает под условие 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.
Особенность этого скрипта в том, что он преобразует все столбцы каждой строки с 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}"
Лс позицииН. Однако индексация равна нулю, поэтому диапазон $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
︙
Конечно, у вас, похоже, все месяцы удвоены, поэтому они удвоены и в выводе. Возможно, добавьте тест для содержимого второго столбца или запустите его с чем-то вроде этого, чтобы проверить только строки с указанным идентификатором:
grep DC holiday_india.txt | bash holiday.sh
(Конечно, это также пропустит строки заголовков. Или вы можете проверить правильность месяца/года в начале строки.)
Это было помечено как ksh, но я использовал bash. Копия ksh
I have поддерживает , что, как мне кажется, было единственным новым синтаксисом, который я использовал.${foo:N:L}