Как мне выровнять столбцы в общих элементах, но дать разным элементам их собственные строки?

&& и || - логические операторы. && - это логический оператор И, а bash использует сокращенное вычисление , поэтому вторая команда выполняется только в том случае, если есть шанс, что все выражение может быть истинным. Если первая команда считается ложной (возвращается с ненулевым кодом выхода), все И-выражение никогда не может стать истинным, поэтому нет необходимости оценивать вторую команду.

Та же самая логика применима аналогично к логическому ИЛИ, ||: если первая команда выполнена успешно, все ИЛИ-выражение станет истинным, поэтому нет необходимости вычислять вторую команду.

1
06.12.2018, 22:32
2 ответа

Вот решение «грубой силы» в сценарии оболочки с использованием pasteи read.

#!/bin/sh

paste a.txt b.txt c.txt |
while read -r a b c; do
    if [ "$a" = "$b" ] && [ "$b" = "$c" ]; then
        printf '%s\t%s\t%s\n' "$a" "$b" "$c"
    elif [ "$a" = "$b" ]; then
        printf '%s\t%s\n\t\t%s\n' "$a" "$b" "$c"
    elif [ "$a" = "$c" ]; then
        printf '%s\t\t%s\n\t%s\n' "$a" "$c" "$b"
    elif [ "$b" = "$c" ]; then
        printf '%s\n\t%s\t%s\n' "$a" "$b" "$c"
    else
        printf '%s\n\t%s\n\t\t%s\n' "$a" "$b" "$c"
    fi
done

Вероятно, есть более элегантное решение, но я не мог придумать хорошее сразу.

Возможно, вы могли бы использовать awkвместо этого, если хотите. --Я думаю, что результат будет очень похожим. (Одно из преимуществ использования awkзаключается в том, что он потенциально может выполнять работу pasteодновременно, если это вам полезно.)

0
27.01.2020, 23:42
BEGIN {
    # We assume the default input field separator (changeable with "-F")
    # Output will be tab delimited.
    OFS = "\t"
}
{
    # The number of output records that this input record results in.
    k=0

    # "seen" records which new record a field should be part of.
    # There may be NF new records for each input record if all
    # fields are unique.
    delete seen

    # "a" holds all data for the new output records.
    # It's basically a 2-dimensional NFxNF matrix
    # encodod in a 1-dimensional array.
    delete a

    # Iterate over the fields
    for (i=1; i<=NF; ++i) {
        if (!seen[$i]) {
            # This data has not been seen before (in this input record),
            # assign it to the next output line.

            seen[$i] = ++k
        }

        # Assign the input field to the right spot
        a[(seen[$i]-1)*NF + i] = $i
    }

    # Save NF as this is reset by emptying $0 later.
    nf = NF

    # Create and output new lines
    for (j = 1; j<=k; ++j) {
        $0 = ""

        # Create new output record
        for (i = 1; i<=nf; ++i)
            $i = a[(j-1)*nf + i]

        # Output record
        print
    }
}

Тестирование на заданных данных:

$ awk -f script.awk file
1       1       1
2       2       2
3
        4       4
5       5       5
1       1
                2
3       3       3

Тестирование на других данных:

$ cat file
a b c e
1 2 1 1
2 1 1 1
1 1 1 2
$ awk -f script.awk file
a
        b
                c
                        e
1               1       1
        2
2
        1       1       1
1       1       1
                        2
1
27.01.2020, 23:42

Теги

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