Найдите несколько слов и напечатайте следующие числа в одной строке

В for word in $line,содержимое переменной lineразбивается на слова и затем расширяется для имен файлов (см. также этивопросы). Затем цикл выполняется один раз для каждого результирующего значения (или «слова» ). В этом случае, однако, есть только одна итерация цикла, так как оператор breakостанавливает выполнение цикла. В результате значение res, установленное на этой первой итерации цикла, остается, и эффект такой же, как при выборе первого слова, разделенного пробелом -, из line.

Были бы лучшие способы написать это, мы могли бы, например,. удалите имя файла с расширениями оболочки. Это выведет23:

line='23 somefilename'
res="${line%% *}"
echo "$res"

Или просто пусть wcне выводит имя файла с самого начала, перенаправляя файл на стандартный ввод wcвместо передачи имени файла на wc. Сравните эти два:

$ wc -c foo.txt
8 foo.txt
$ wc -c < foo.txt
8

0
13.04.2021, 05:28
3 ответа

Я думаю, вам лучше использовать ассоциативный массив вместо набора отдельных переменных:

line="AA 10 BB 20 DD 14 GG 14"
read -ra words <<< "$line"

declare -A cnt
for ((i = 0; i < ${#words[@]}; i += 2)); do
    label=${words[i]} 
    num=${words[i+1]}
    cnt[${label:0:1}]=$num
done

declare -p cnt      # => declare -A cnt=([G]="14" [D]="14" [B]="20" [A]="10" )

Сейчас:

letter=A
echo "$letter count is ${cnt[$letter]:-0}"  # => A count is 10
letter=C
echo "$letter count is ${cnt[$letter]:-0}"  # => C count is 0

С отдельными переменными мы можем использовать declareдля "динамических" имен переменных:

for a in {a..z}; do
    declare "${a}Cnt=0"
done
line="AA 10 BB 20 DD 14 GG 14"
declare -l letter     # lowercase
while [[ $line =~ ([A-Z]+)" "([0-9]+)(.*) ]]; do
    letter=${BASH_REMATCH[1]:0:1}
    declare "${letter}Cnt=${BASH_REMATCH[2]}"
    line=${BASH_REMATCH[3]}
done

Теперь имеем:

$ set | grep '.Cnt'
aCnt=10
bCnt=20
cCnt=0
dCnt=14
eCnt=0
fCnt=0
gCnt=14
hCnt=0
iCnt=0
jCnt=0
kCnt=0
lCnt=0
mCnt=0
nCnt=0
oCnt=0
pCnt=0
qCnt=0
rCnt=0
sCnt=0
tCnt=0
uCnt=0
vCnt=0
wCnt=0
xCnt=0
yCnt=0
zCnt=0
1
28.04.2021, 22:52
 for i in {A..Z}; do grep -i "$i" filename >/dev/null; if [[ $? == 0 ]]; then awk -v i="$i"  '{for(j=1;j<=NF;j++){if($j ~ i ){print substr($j,1,1)"Cnt="$(j+1)}}}' filename; else echo -e "$i""Cnt=0"; fi; done

выход

ACnt=10
BCnt=20
CCnt=0
DCnt=14
ECnt=0
FCnt=0
GCnt=14
HCnt=0
0
28.04.2021, 22:52

Одинаково сумасшедший awk.....так как это тег

awk -vRS=" " '{a=tolower(substr($0,1,1)); getline; aa[a]=$0}
     END{for (a=97; a<=122; a++) {A=sprintf("%c",a); print A"Cnt="aa[A]+0}}' file

Побить рекорды RSна , ассоциативный массив и немного покерной мешанины со строковыми символами

aCnt=10
bCnt=20
cCnt=0
dCnt=14
eCnt=0
fCnt=0
gCnt=14
hCnt=0
1
28.04.2021, 22:52

Теги

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