mrng(){ sed "$(set -f;unset IFS rng l;n='
';[ -n "$ZSH_VERSION" ] && emulate sh
prng() for m do rng=${r%%"$m"*}${r##*"$m"} _l=$((_l+1))
printf "\n\n%s\n/$pat/{\n\t:$l.$_l\n\tn" $m
printf "\n\n%s\n\t/$pat/b$l.$_l.0" $rng
printf "\n\tb$l.$_l\n\t:$l.$_l.0\n}"
done
pat=$( printf %s "${1:-%m}$n"| sed -n 's/%/&&/g;l'|
sed ":n$n\$!N;s/\\\n//;tn${n}s/\$$//"); shift
r=$( locale -c LC_TIME|sed '4!d;y/;/ /')
for m do case $m in (-) rng=$r ;;
(-*) rng=${r%%"${m#-}"*}${m#-} ;;
(*-) rng=${m%-}${r##*"${m%-}"} ;;
(*-*) rng=${m%%-*}${r##*"${m%%-*}"} ;
case $rng in (*${m##*-}*)
rng=${rng%%"${m##*-}"*}${m##*-} ;;(*)
rng=$rng\ ${r%%"${m##*-}"*}${m##*-};;esac
;;esac; : $((l+=1))
prng ${rng:="$m"}; unset rng
done| sed " 1d;s/.*\(...\)\(\n\)\(.*[^%]\(%%\)*\)%m//
/./!{N;N$n};/\n/D"
);d"
}
Esta é uma função de shell - você precisará adaptá-la em um script de shell se é assim que você planeja chamá-lo ou avaliá-lo no shell atual. Você pode chamá-lo assim:
mrng "$pat" Jan-Mar Jun Sep-Nov <infile
Ele também aceita intervalos abertos, como -
para significar todos ou Mar-
, de março a dezembro. E os argumentos não têm como intervalos - como acima, Jun
está bem.
Na verdade, no entanto, ele não interpreta os nomes dos meses - ele coleta aqueles do locale
utility (que é uma dependência) e trabalha com o que a localidade atual diz os nomes dos meses de 3 caracteres são.
Ele pode fazer intervalos aleatórios e, na verdade, quase todos eles realmente fazem fazer quebra, ou, talvez seja melhor dizer, acumular, de qualquer maneira.
Ele espera que seu primeiro argumento seja um padrão BRE compatível com sed
- com a exceção de que, onde quer que você espere encontrar o nome do mês, você deve usar %m
. Você também pode inserir vários %m
s - o que você pode fazer se quiser apenas corresponder linhas como Mar...Mar
- Jun...Jun
. Provavelmente isso não é incrivelmente útil, mas talvez ...?
Embora pareça complicado, mais da metade disso é dedicado à análise de argumentos - o sed
é relativamente simples, afinal. Por exemplo, se eu fizer:
mrng %m Dec-Jan
... ele gerará um script sed
semelhante a:
/Dec/{
:1.1
n
/Jan/b1.1.0
/Feb/b1.1.0
/Mar/b1.1.0
/Apr/b1.1.0
/May/b1.1.0
/Jun/b1.1.0
/Jul/b1.1.0
/Aug/b1.1.0
/Sep/b1.1.0
/Oct/b1.1.0
/Nov/b1.1.0
b1.1
:1.1.0
}
/Jan/{
:1.2
n
/Feb/b1.2.0
/Mar/b1.2.0
/Apr/b1.2.0
/May/b1.2.0
/Jun/b1.2.0
/Jul/b1.2.0
/Aug/b1.2.0
/Sep/b1.2.0
/Oct/b1.2.0
/Nov/b1.2.0
/Dec/b1.2.0
b1.2
:1.2.0
};d
... que acaba sendo muito código, mas a maioria não é avaliada na maioria das vezes. Em uma linha típica, ele verifica se corresponde a Dec e, se não, se corresponde a Jan e, se não, a exclui da saída.
Mas uma vez que corresponda a um desses padrões, começará um loop de ramificação simples. Portanto, dado o exemplo acima, se uma linha corresponder a Dec, ela será impressa e sobrescrita com a linha de entrada n
ext. Se a nova linha corresponder a qualquer mês mas Dez, sed
b
será ranqueado com o :1.1.0
label - o que significa que a linha ainda precisa ser avaliada em relação a Jan
- onde obterá semelhante tratamento - mas não será avaliado em qualquer mês anterior Dez. Se não corresponder a nenhum mês, mas a Dez, então sed
b
terá até o rótulo :1.1
, que recebe a linha impresso e o n
ext puxado e etc.
Se eu fizesse -
, então seria uma função semelhante à anterior - cada uma contendo seu próprio rótulo :
exclusivo - para cada mês dentro do intervalo. Isso significa que os argumentos da linha de comando têm efeito cumulativo. Alguns exemplos:
printf %s\n 'not a month' May 'not a month' 'also not a month' Apr |
m_rng %m Apr May
As impressões acima:
May
not a month
also not a month
Porque May
vem antes de Apr
na entrada, mas depois de Apr
na linha de comando. No entanto, é uma heurística bastante bruta. A entrada é processada na ordem dos argumentos da linha de comando, mas assim que um ciclo completo é feito, o processamento recomeça, então ...
printf %s\n 'not a month' May 'not a month' 'also not a month' Jun Apr |
m_rng %m Apr May
... imprime ...
May
not a month
also not a month
Apr
Como o ciclo é interrompido em Jun
, a linha é excluída e o processamento é iniciado novamente do topo com a próxima linha de entrada - Apr
.
De qualquer forma, para o seu padrão, você deve usar:
mrng '^\([^ ]\{1,\} *\)\{3\}%m' [month args]