Переупорядочивание строк и объединение других на основе определенных критериев

Con matrices zsh(zshlas matrices pueden contener cualquier secuencia arbitraria de bytes, incluso 0 ).

(también tenga en cuenta que puede hacer typeset -U arraypara garantizar que sus elementos sean únicos ).

establecer membresía

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 $elementen la matriz (o 0 si no se encuentra ). Quitare(para exact )para que $elementse 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 $~elementpara que se tome como un patrón ).

establecer intersección

common=("${(@)set1:*set2}")

${set1:*set2}realiza la intersección del arreglo, pero se necesita la sintaxis "${(@)...}"para preservar los elementos vacíos.

establecer igualdad

[[ ${(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 qcita 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 opara ordenarlos. Consulte también el indicador u(único )para eliminar duplicados.

[[ ${(j: :)${(qo)array1}} = ${(j: :)${(qo)array2}} ]]

establecer cardinalidad

n=$#array

prueba de subconjunto

if ((${#array1:*array2} == ${#array2})); then
  echo '$array2 is included in $array1'
fi

sindicato

union=("$array1[@]" "$array2[@]")

(consulte typeset -Uarriba o el indicador de expansión de parámetros upara tomar el caso de duplicados ). Nuevamente, si la cadena vacía no es uno de los valores posibles, puede simplificar a:

union=($array1 $array2)

complemento

complement=("${(@)array1:|array2}")

para los elementos de $array1que no están en $array2.

mínimo/máximo (comparación léxica)

min=${${(o)array}[1]} max=${${(o)array}[-1]}

mínimo/máximo (comparación de enteros decimales)

min=${${(no)array}[1]} max=${${(no)array}[-1]}
2
26.06.2019, 13:41
2 ответа

У меня работает этот 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
2
27.01.2020, 21:58

С 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-й транзакции? )поэтому я просто объединил суммы для всех дубликатов и оставил суммы для не -дубликатов. Если это не работает для вас, пожалуйста, уточните требования в вашем вопросе.

2
27.01.2020, 21:58

Теги

Похожие вопросы