Tôi đang có một danh sách dài các địa chỉ IP không theo thứ tự. Tôi cần tìm xem có bao nhiêu địa chỉ IP trước / sau một địa chỉ IP cụ thể. Làm thế nào tôi có thể đạt được điều này?
Tôi đang có một danh sách dài các địa chỉ IP không theo thứ tự. Tôi cần tìm xem có bao nhiêu địa chỉ IP trước / sau một địa chỉ IP cụ thể. Làm thế nào tôi có thể đạt được điều này?
Câu trả lời:
Có lẽ dễ nhất là
sed -n '/pattern/{=; q;}' file
Cảm ơn @JoshepR đã chỉ ra lỗi
dc
, bản thân tôi, có lẽ.
Tôi đã làm điều này theo hai cách, mặc dù tôi nghĩ rằng tôi thích điều này nhất:
: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
$(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do printf '%s line%s :\t%d\n' \
"${n%s}" "${n##*[!s]}" $((${n%s}l))
done
Điều đó lưu tất cả những cái đó như các biến shell hiện tại - và đánh giá chúng trong vòng lặp for sau đó cho đầu ra. Nó đếm tổng số dòng trong tệp wc
và nhận được số dòng phù hợp đầu tiên với sed
.
Đầu ra của nó:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Tôi cũng đã làm:
sed -n "/$IP/=;\$=" ~/file |
tr \\n \ | {
IFS=' ' read ml ll
printf '%s line%s:\t%d\n' \
last '' $((ll=${ll##* }))
match '' $ml \
after s "$((al=ll-ml-1)) \
before s $((bl=ml-1))
}
sed
chỉ in các số dòng phù hợp và cuối cùng, sau đó tr
dịch các \n
ewlines can thiệp sangvà read
đọc sed
kết quả đầu tiên vào $ml
và tất cả những kết quả khác $ll
. Nhiều trường hợp khớp có thể được xử lý bằng cách tước tất cả trừ kết quả cuối cùng ra khỏi bản $ll
mở rộng khi thiết lập lại sau.
Đầu ra của nó:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Cả hai phương pháp đều được kiểm tra trên tệp được tạo theo cách sau:
IP='some string for which I seek'
for count in 1 2 3 4 5
do printf '%.199d%s\n' 0 "$IP"
done | tr 0 \\n >~/file
Nó không, theo số dòng:
"$IP"
đến \n
ewlinetr
- dịch các số 0 thành \n
ewlines sau đó vào~/file
Đây là một ít mã Perl thực hiện điều đó:
perl -ne '
if(1 .. /192\.168\.1\.1/) { $before++ }
else { $after++ }
$before--; # The matching line was counted
END{print "Before: $before, After: $after\n"}' your_file
Điều này đếm tổng số dòng trước và sau dòng chứa IP 192.168.1.1
. Thay thế bằng IP mong muốn của bạn.
Không dùng gì ngoài Bash:
before=0
match=0
after=0
while read line;do
if [ "$line" = 192.168.1.1 ];then
match=1
elif [ $match -eq 0 ];then
before=$(($before+1))
else
after=$(($after + 1))
fi
done < your_file
printf "Before: %d, After: %d\n" "$before" "$after"
$.
thay vì quầy?
$after
để $. - $before
.
$. - 1
, lưu $.
vào $tmp
. Kết thúc in $. - $tmp
. Vì vậy, chúng tôi không cần truy cập cho cả trước và sau. Tất nhiên nó ít đọc hơn của bạn.
Tôi đã thử các lệnh sau, hơi phức tạp, nhưng sẽ cho kết quả chính xác:
Sau:
a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l
Trước:
echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l
Grep
có một tính năng có thể đếm số lần một mẫu cụ thể được tìm thấy. Nếu bạn sử dụng -c
lệnh sẽ làm như vậy. Với lệnh -c
and -v
, điều này sẽ tính số lần không khớp với một mẫu cụ thể
Thí dụ:
grep -c -v <pattern> file
Vì vậy, nếu bạn thử một cái gì đó như:
grep -c -v 192.168.x.x file.log
Cần làm việc.