Con matrices zsh
(zsh
las matrices pueden contener cualquier secuencia arbitraria de bytes, incluso 0 ).
(también tenga en cuenta que puede hacer typeset -U array
para garantizar que sus elementos sean únicos ).
if ((${array[(Ie)$element]})); then
echo '$element is in $array'
fi
(usando el indicador de subíndice de matriz I
, para obtener el índice de la última aparición de $element
en la matriz (o 0 si no se encuentra ). Quitare
(para e
xact )para que $element
se tome como patrón)
if ((n = ${(M)#array:#$element})); then
echo "\$element is found $n times in \$array'
fi
${array:#pattern}
es una variación de ksh ${var#pattern}
que elimina los elementos que coinciden con el patrón en lugar de simplemente eliminar la parte principal que coincide con el patrón. El(M)
(para emparejado)invierte el significado y elimina todos menos los elementos emparejados (use $~element
para que se tome como un patrón ).
common=("${(@)set1:*set2}")
${set1:*set2}
realiza la intersección del arreglo, pero se necesita la sintaxis "${(@)...}"
para preservar los elementos vacíos.
[[ ${(j: :)${(q)array1}} = ${(j: :)${(q)array2}} ]]
Comprueba si las matrices son idénticas (y en el mismo orden ). El indicador de expansión del parámetro q
cita los elementos (para evitar problemas con cosas como a=(1 "2 3")
frente a b=("1 2" 3)
), y (j: :)
los une con un espacio antes de hacer una comparación de cadenas.
Para comprobar que tienen los mismos elementos, independientemente del orden, utilice la bandera o
para ordenarlos. Consulte también el indicador u
(único )para eliminar duplicados.
[[ ${(j: :)${(qo)array1}} = ${(j: :)${(qo)array2}} ]]
n=$#array
if ((${#array1:*array2} == ${#array2})); then
echo '$array2 is included in $array1'
fi
union=("$array1[@]" "$array2[@]")
(consulte typeset -U
arriba o el indicador de expansión de parámetros u
para tomar el caso de duplicados ). Nuevamente, si la cadena vacía no es uno de los valores posibles, puede simplificar a:
union=($array1 $array2)
complement=("${(@)array1:|array2}")
para los elementos de $array1
que no están en $array2
.
min=${${(o)array}[1]} max=${${(o)array}[-1]}
min=${${(no)array}[1]} max=${${(no)array}[-1]}
У меня работает этот awk-скрипт GNU:
#! /usr/local/bin/awk -f
BEGIN { FS = "[[:space:]][[:space:]]+" }
function dump() {
for (acct in post) { # dump unmerged postings of current transaction
if (post[acct])
print post[acct];
}
if (merged) { # dump merged posting, if any
printf " %s\n", merged
}
merged = ""; # clear variables for next round
delete post;
txn = "";
}
!NF && txn { # blank line, end of transaction
dump();
print;
next
}
END { # end-of-file, print merged postings of last txn
dump();
}
!txn { # new transaction
txn = $0;
print;
next
}
{
acct = $2;
amt = $3
}
amt ~ /-/ { # negative amounts, keep for later
if (acct in post) { # duplicate entry
if (!merged || merged == acct) { # only merge and clear one duplicate account
post[acct] = "";
merged = acct;
}
else # tack on to existing record without merging
post[acct] = post[acct] "\n" $0
}
else
post[acct] = $0
next
}
1
В действии:
~./foo.awk foo
2019/05/31 (MMEX948) Gürmar
Expenses:Food:Groceries:Meat ₺28,14
Expenses:Food:Groceries:Meat ₺28,14
Expenses:Food:Groceries:Basic ₺3,45
Expenses:Food:Groceries:Produce ₺15,00
Assets:Cash:Marina
2019/06/01 (MMEX932) A101
Expenses:Food:Groceries:Basic $5.50
Assets:Cash:Marina $-2.50
Assets:Cash:Caleb $-3.00
2019/06/01 (MMEX931) Şemikler Pazar Yeri
Expenses:Food:Groceries:Basic ₺24,00
Expenses:Food:Groceries:Meat ₺31,00
Expenses:Food:Groceries:Produce ₺65,00
Assets:Cash:Marina
С GNU awk для gensub (), массивы массивов и отсортированные _в:
$ cat tst.awk
BEGIN { RS=""; FS="\n"; localeDecPt="."; PROCINFO["sorted_in"]="@val_num_desc" }
{
delete sum
print $1
denom = gensub(/.*([^0-9.,-]).+$/,"\\1",1,$2)
for (i=2; i<=NF; i++) {
account = gensub(/[[:space:]]+[^[:space:]]+$/,"",1,$i)
amount = gensub(/.*[^0-9.,-](.+)$/,"\\1",1,$i)
inputDecPt = gensub(/[0-9-]+/,"","g",amount)
sum[account] += gensub("["inputDecPt"]",localeDecPt,"g",amount)
}
for (account in sum) {
amount = denom gensub("["localeDecPt"]",inputDecPt,"g",sprintf("%0.2f",sum[account]))
printf "%-*s%*s\n", 40, account, 10, amount
}
print ""
}
.
$ awk -f tst.awk file
2019/05/31 (MMEX948) Gürmar
Expenses:Food:Groceries:Meat ₺56,28
Expenses:Food:Groceries:Produce ₺15,00
Expenses:Food:Groceries:Basic ₺3,45
Assets:Cash:Marina ₺-74,73
2019/06/01 (MMEX932) A101
Expenses:Food:Groceries:Basic $5.50
Assets:Cash:Marina $-2.50
Assets:Cash:Caleb $-3.00
2019/06/01 (MMEX931) Şemikler Pazar Yeri
Expenses:Food:Groceries:Produce ₺65,00
Expenses:Food:Groceries:Meat ₺31,00
Expenses:Food:Groceries:Basic ₺24,00
Assets:Cash:Marina ₺-120,00
Если .
не является десятичной точкой в вашей локали, просто измените localeDecPt="."
на любое другое. Если ваши вводимые суммы содержат, скажем, запятые в качестве разделителей тысяч, тогда опубликованный мной код не будет работать, и вы должны предоставить входные данные, которые включают это для проверки. Я жестко -закодировал ширину выходного поля на 40 и 10 -, вы можете довольно легко рассчитать максимальную ширину каждого поля и использовать ее вместо этого или использовать вкладки в качестве OFS и направить вывод на column
, но это не так. не похоже, что все это было бы необходимо.
Честно говоря, я не понимаю ваших требований относительно того, что объединять и как идентифицировать дубликаты (, например. почему бы не объединить все дубликаты в первую транзакцию и почему убрать сумму с одного не дублирующегося счета -во 2-й транзакции? )поэтому я просто объединил суммы для всех дубликатов и оставил суммы для не -дубликатов. Если это не работает для вас, пожалуйста, уточните требования в вашем вопросе.