&&
и ||
- логические операторы. && - это логический оператор И, а bash использует сокращенное вычисление , поэтому вторая команда выполняется только в том случае, если есть шанс, что все выражение может быть истинным. Если первая команда считается ложной (возвращается с ненулевым кодом выхода), все И-выражение никогда не может стать истинным, поэтому нет необходимости оценивать вторую команду.
Та же самая логика применима аналогично к логическому ИЛИ, ||: если первая команда выполнена успешно, все ИЛИ-выражение станет истинным, поэтому нет необходимости вычислять вторую команду.
Вот решение «грубой силы» в сценарии оболочки с использованием 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
одновременно, если это вам полезно.)
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