Preciso de um script para converter esta lista de feriados em formato de data. Meu arquivo de entrada
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
Agora 123456789012345678901234567890 é como a data quando chega o 0 pela primeira vez, é 10 e então 1 significa 11 e assim por diante. ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14............
Então eu criei um script onde quer que Y esteja presente, ele é convertido em data, suponha que na primeira linha Y esteja presente em 1, 2,9,6,3,9
No meu script, cortei cada linha da coluna 21-52 e verifiquei se essa coluna é Y, se sim, ela é convertida em data, como se Y estivesse presente na coluna número 23. Então estou subratificando (número da coluna - 20) ele irá me dê 3 E então estou usando o operador concat para marcar a data.
Abaixo está meu roteiro. Mas estou enfrentando um problema quando não há Y em nenhuma coluna, meu var é considerado em branco e o branco também está em condição verdadeira.
var=echo $f1 | cut -c$i
if [[ "$var"='Y' ]] ;
E meu script está abaixo.
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`
Por favor, deixe-me saber o que farei para que, quando não houver nada em var , não caia na condição If true.
O/p deste script é que ele converte todas as colunas de cada linha de 21 a 52 em datas não onde Y está presente.
Espero ter esclarecido agora.
Responder1
Ok, copiei seu script abaixo e corrigi o recuo para facilitar a leitura. (E também mudei os crases $()
e removi os nomes de arquivos fixos porque gosto assim.)
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
Duas coisas saltam à vista:
if [[ "$var"='Y' ]] ; then
Isso não funciona; precisa de espaços ao redor do sinal de igual. Experimente e veja o que [[ X=Y ]] && echo foo
acontece.
Aqui também
var=$(echo $f1 | cut -c$i)
f1
contém algo como 012016 821 YY Y Y Y Y
, mas como não está entre aspas, ele é expandido e, em seguida, dividido por palavras ao longo dos espaços, após o que echo
imprime todas as palavras separadas porsolteiroespaços, resultando em 012016 821 YY Y Y Y Y
. Você poderia consertar isso adicionando aspas: echo "$f1" | cut -c$i
, mas também há uma substring de comprimento"${f1:N:L}"
euda posiçãoN. Porém, ele é indexado em zero, portanto, o intervalo de $i
precisará ser modificado.
Então,
echo "$year-$month-$date"
Isso pode ser alterado para printf "%04d-%02d-%02d\n" "$year" "$month" "$date"
garantir que a data seja sempre impressa com dois dígitos e para proteger contra possíveis valores anômalos de $year
.
É melhor mover as atribuições de mês e ano para o loop externo, já que elas permanecem as mesmas durante toda a linha.
Agora temos:
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
A saída parece correta quando eu a executo com 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
︙
É claro que parece que todos os meses dobraram, então a produção também dobrou. Talvez adicione um teste para o conteúdo da segunda coluna ou execute-o com algo assim para verificar apenas as linhas com o ID fornecido:
grep DC holiday_india.txt | bash holiday.sh
(É claro que isso também pularia as linhas do cabeçalho. Ou você poderia verificar se o mês/ano está correto no início da linha.)
Isso foi marcado com ksh, mas usei bash. A cópia de ksh
I have support , que acho que foi a única sintaxe nova que usei.${foo:N:L}