#linux #bash #shell #awk #sh
#linux #bash #оболочка #awk #sh
Вопрос:
У меня есть файл list.txt содержащий такие данные, как этот
hvar-mp-log.hvams europe@gmail.com asia@gmail.com aust@gmail.com
mvar-mp-log.mvams japan@gmail.com ant@gmail.com
mst-mp-log.mst korea@gmail.com maxwell@gmil.com antra@gamil.com
pif-mp-log-pif atlas@gmail.com korea@gamil.com japan@gmail.com mexco@gmail.com
Мне нужно сопоставить строку в list.txt и выведите соответствующие данные столбца string.
Если строка=mst-mp-log.mst print korea@gmail.com maxwell@gmil.com antra@gamil.com
Я могу сопоставить string=mst-mp-log.mst, как в этом примере, дает мне только информацию о втором столбце, например korea@gmail.com
string="mst-mp-log.mst"
awk -v var="$string" '$1 == var {print $2}' list.txt
как распечатать совпадающую строку со всеми идентификаторами почты. ожидаемый результат должен быть следующим
korea@gmail.com maxwell@gmil.com antra@gamil.com
Ответ №1:
$ awk -v tgt='mst-mp-log.mst' '$1==tgt{$1=""; $0=$0; $1=$1; print}' file
korea@gmail.com maxwell@gmil.com antra@gamil.com
Объяснение:
$1==tgt
— очевидно$1=""
— устанавливает исходное значение $ 1 равным нулю и восстанавливает значение $ 0, но $ 1 по-прежнему является полем (только теперь с нулевым значением), поэтому оно все еще существует в записи, и поэтому между $ 1 и $ 2 находится пробел (OFS), как и между всеми полями.$0=$0
— повторно разбивает запись на новые номера полей, поэтому исходный $ 1 удаляется, а $ 2 становится новым $ 1, но не изменяет фактическую строку, составляющую запись, поэтому пробел все еще существует в ее начале$1=$1
— принудительно восстанавливает значение $ 0 из его полей и, таким образом, удаляет начальный пробелprint
— очевидно
Здесь вы можете пошагово увидеть, что происходит с записью и полями:
awk -v tgt='mst-mp-log.mst' '$1==tgt {
printf "nRecord original:n<%s>n", $0 ; for (i=1; i<=NF; i ) printf "tField %d/%d [%s]n", i, NF, $i
$1=""
printf "nRecord after $1="":n<%s>n", $0 ; for (i=1; i<=NF; i ) printf "tField %d/%d [%s]n", i, NF, $i
$0=$0
printf "nRecord after $0=$0:n<%s>n", $0 ; for (i=1; i<=NF; i ) printf "tField %d/%d [%s]n", i, NF, $i
$1=$1
printf "nRecord after $1=$1:n<%s>n", $0 ; for (i=1; i<=NF; i ) printf "tField %d/%d [%s]n", i, NF, $i
print ""
print
}' file
Record original:
<mst-mp-log.mst korea@gmail.com maxwell@gmil.com antra@gamil.com>
Field 1/4 [mst-mp-log.mst]
Field 2/4 [korea@gmail.com]
Field 3/4 [maxwell@gmil.com]
Field 4/4 [antra@gamil.com]
Record after $1="":
< korea@gmail.com maxwell@gmil.com antra@gamil.com>
Field 1/4 []
Field 2/4 [korea@gmail.com]
Field 3/4 [maxwell@gmil.com]
Field 4/4 [antra@gamil.com]
Record after $0=$0:
< korea@gmail.com maxwell@gmil.com antra@gamil.com>
Field 1/3 [korea@gmail.com]
Field 2/3 [maxwell@gmil.com]
Field 3/3 [antra@gamil.com]
Record after $1=$1:
<korea@gmail.com maxwell@gmil.com antra@gamil.com>
Field 1/3 [korea@gmail.com]
Field 2/3 [maxwell@gmil.com]
Field 3/3 [antra@gamil.com]
korea@gmail.com maxwell@gmil.com antra@gamil.com
Комментарии:
1. Спасибо Эду Мортону за подробное объяснение решения.
Ответ №2:
Альтернативное решение без использования awk
# Capture the search output into bash array
array=( $(grep "$string" list.txt) )
# First column (Index-0) is your search string, remaining are the email IDs, so print array elements starting from Index 1
echo ${array[@]:1}
korea@gmail.com maxwell@gmil.com antra@gamil.com
# Print all array elements separated by space
echo ${array[@]}
mst-mp-log.mst korea@gmail.com maxwell@gmil.com antra@gamil.com
# Find number of elements in array
echo ${#array[@]}
4
# Advantage with this solution is that you can iterate over the array using a for loop:
for str in "${array[@]}"; do
echo $str
done
mst-mp-log.mst
korea@gmail.com
maxwell@gmil.com
antra@gamil.com
Это может потребовать небольшой корректировки, если структура файла изменится