Количество строк, в которых второе поле начинается с определенного символа

Я пытался использовать команды sed и awk

#!/bin/bash
i=`sed -n '1p' l.txt| awk -F "," '{print $1}'`
j=`sed -n '2p' l.txt| awk -F "," '{print $1}'`
if [[ $i == $j ]]
then
awk -F "," 'NR==2{print $2}' l.txt
else
echo "The value is different"
fi

выход

5.5
-1
11.02.2021, 19:42
3 ответа

Самое основное требование выполняется через

awk '$2~/^a/{c++} END{print c+0}'

Это проверит второй столбец; проверьте, начинается ли он с aс помощью сравнения регулярных выражений, и увеличьте счетчик c. В конце -файла -будет напечатан счетчик. Чтобы гарантировать, что число будет напечатано, даже если cникогда не увеличивается, мы печатаем c+0, которое не изменится c, если оно уже не равно -нулю, но принудительно интерпретируется как число, когда c] все еще не инициализирован.

Теперь, чтобы убедиться, что никакие «бродячие» токены из «заголовка» не мешают, первая проверка заключается в том, чтобы убедиться, что первый столбец является целым числом:

awk '$1+0==$1 && $2~/^a/{c++} END{print c+0}'

Идея заключается в том, что $1+0будет интерпретироваться арифметически как «ничего не добавляя», если $1является числом, но будет указывать awkна добавление символа 0, если это «текст», следовательно, $1+0не изменится, только если $1— число.

Для еще более сложной проверки мы можем запретить рассмотрение строк до тех пор, пока не встретится строка «конец заголовка», и, кроме того, пропустить строку сразу после этого:

awk 'f==2&&$2~/^a/{c++} f==1&&NF{f++} $0=="header end"{f=1} END{print c+0}'

Это установит флаг fв 1 при обнаружении строки header end, установите его в 2на первой не-пустой строке после заголовка и только в строках, где f2проверьте второй столбец.

4
18.03.2021, 22:30

Я предлагаю не awkрешение, а grepрешение, основанное на структуре записей:

$ grep "^[0-9]\+[[:blank:]]\+a[0-9]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[0-9]\+$" file | wc -l
2
1
18.03.2021, 22:30

Простые решения

В соответствии с вашим описанием:подсчитайте строки, начинающиеся с a во втором столбце этого достаточно:

awk '$2 ~ /^a/ { count++ } END {print count}' file 

Возможно даже, что команда grep (должна быть быстрее ):

grep -c '^[0-9][0-9]* *a' test.txt

Что также является более конкретным, поскольку требует, чтобы первое поле было числом (, предполагая, что это то, что вам нужно из примера, опубликованного ), а разделитель полей — пробел.

Глядя глубже

Но первое решение, которое вы опубликовали:

awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' file

Делает что-то совсем другое.

При вводе этого файла:

> cat file
header start
stuff
header end
pos1 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
3   a3 AAB  BBB 47
4   b6 AAC  BBB 1000
5   c9 BBA  CBA 20
pos2 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
pos3 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
3   a3 AAB  BBB 47

Размещенный вами код выводит результат для каждого (разного )заголовка:

> awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"=="a[i]-1}' test.txt 
==2
pos1 LV file LVG size==5
pos3 LV file LVG size==3
pos2 LV file LVG size==2

То есть :2 строки для пустого заголовка, 5 строк после заголовка "pos1" и т.д....

Я не знаю, нужен ли вам такой счет или нет. Я также не понимаю, почему вы вычитаете 1 из счета.

Единственным дополнительным требованием является подсчет только тех строк, в которых второе поле начинается сa

$ awk '/LVG/{p=$0} $2 ~ /^a/ {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1

Если вам также нужно, чтобы первое поле было числом (, аналогично команде grep выше):

$ awk '/LVG/{p=$0} ($1+0!=0)&&($2~/^a/) {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1
0
18.03.2021, 22:30

Теги

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