Как насчет удаления записей из массива поиска по мере их сопоставления, а затем вывода того, что осталось в конце?
$ awk 'NR==FNR {a[$1]; next}
$1 in a {print; delete a[$1]}
END {for (i in a) print i, "10 20"}
' ref.txt file.txt
Doc_A 123 abc
Doc_B 123 abc
Doc_C 123 abc
Doc_D 10 20
Doc_E 10 20
Doc_F 10 20
(Обратите внимание, что awk не гарантирует порядок обхода массива -, если это проблема.)
В то время как NR==FNR
мы обрабатываем первый именованный файл(ref.txt
):мы создаем запись массива с его первым (в этом случае только полем )в качестве его индекса, а затем переходим к записи next
. Нам не нужно присваивать значение элементу массива.
В противном случае мы обрабатываем второй именованный файл(file.txt
). Мы проверяем, имеет ли его первый столбец совпадение с массивом a
, который мы создали из эталонного файла, и печатаем запись $0
, если оно есть. Затем удаляем запись.
Удаление служит двум целям: :оно «уникализирует» совпадение, потому что в следующий раз, когда мы проверим $1 in a
на то же самое $1
, ответ будет ложным. Это также означает, что после того, как все строки file.txt
были обработаны, любые оставшиеся элементы в a
не были сопоставлены -, мы можем распечатать их в вашем «фиксированном» формате в блоке END
.
Мне неизвестен способ сделать то, что вам нужно, в Bash (, кроме опций, которые вы уже определили ).
Если бы я пытался сделать то, что вы хотите, я бы, вероятно, сделал что-то вроде:
#!/bin/bash
overall_status=failed
value=$1
if (( value > 0 )); then echo "value > 0"
elif (( value > 1 )); then echo "value > 1"
elif (( value > 2 )); then echo "value > 2"
elif (( value > 3 )); then echo "value > 3"
else overall_status=ok
fi
if [[ "$overall_status" != ok ]]; then
echo 'EARLY EXIT' >&2
exit 1
fi
Простой способ раннего выхода из группы команд — это и список с использованием &&
, который прерывается при первом сбое, что является короткой заменой операторов if
или case
.. Замена фиктивного цикла while в вашем примере на этот:
(( value > 0 )) && echo "$value > 0" &&
(( value > 1 )) && echo "$value > 1" &&
(( value > 2 )) && echo "$value > 2" &&
(( value > 3 )) && echo "$value > 3" &&
overall_status=ok
Или аналогично вашей анонимной функции zsh, почему у вас нет именованной функции bash.
#!/bin/bash
arg=$1
function f() {
value=$1
(( value > 0 )) && echo "$value > 0" || return 1
(( value > 1 )) && echo "$value > 1" || return 1
(( value > 2 )) && echo "$value > 2" || return 1
(( value > 3 )) && echo "$value > 3" || return 1
return 0
}
if f arg; then
exit 0
else
echo 'EARLY EXIT' >&2
exit 1
fi
Еще варианты:
подоболочка и используйте exit
, чтобы выйти из нее:
(
... || exit # failure
... && exit # success
) || die 'subshell failed'
поместите свой код в условную часть цикла:
while
... || break
... && break
do break; done
Обратите внимание, однако, что статус выхода из цикла всегда будет равен 0.
При подходе с циклом for
вы можете использовать ! break
для выхода из цикла со статусом отказа (, но не с помощью pdksh или его производных):
for once in total; do
... || ! break
... && continue # same as break
done
Обратите внимание, что при приближении к петле вы можете выйти из более чем одной охватывающей петли с помощью break 2
, break 3
...
источник здесь -документ:
. /dev/fd/3 3<< 'EOF'
... || return
... && return
EOF