Làm thế nào để đếm số lượng ký tự trong một dòng, ngoại trừ một ký tự cụ thể?


9

Đây là một phần của tập tin

N W N N N N N N N N N
N C N N N N N N N N N
N A N N N N N N N N N
N N N N N N N N N N N
N G N N N N N N N N N
N C N N N C N N N N N
N C C N N N N N N N N

Trong mỗi dòng tôi muốn đếm tổng số ký tự không phải là "N"

đầu ra mong muốn của tôi

1
1
1
0
1
2
2

Sử dụng sedđể thay thế những thứ bạn không quan tâm và awkđể đếm chiều dài còn lạised 's/N//g ; s/\s//g' file | awk '{ print length($0); }'
Rolf

Câu trả lời:


13

Giải pháp GNU awk :

awk -v FPAT='[^N[:space:]]' '{ print NF }' file
  • FPAT='[^N[:space:]]'- mẫu xác định giá trị trường (bất kỳ ký tự nào ngoại trừ Nchar và khoảng trắng)

Sản lượng dự kiến:

1
1
1
0
1
2
2


7

giả sử rằng số lượng là cần thiết cho mỗi dòng khác với ký tự khoảng trắng và N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • giá trị trả về trlà có bao nhiêu ký tự được thay thế
  • c để bổ sung cho bộ ký tự đã cho
  • Lưu ý việc sử dụng -ltùy chọn, loại bỏ ký tự dòng mới khỏi dòng đầu vào để tránh lỗi tắt và cũng thêm ký tự dòng mới cho câu lệnh in


Một giải pháp chung chung hơn

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -atùy chọn tự động phân chia dòng đầu vào trên khoảng trắng, được lưu trong @Fmảng
  • grep {$_ ne "N"} @Ftrả về mảng của tất cả các phần tử @Fkhông khớp với chuỗiN
    • tương đương regex sẽ là grep {!/^N$/} @F
  • sử dụng scalarsẽ cho số phần tử của mảng

6

Giải pháp thay thế awk :

awk '{ print gsub(/[^N[:space:]]/,"") }' file
  • gsub(...)- gsub()Hàm trả về số lần thay thế được thực hiện.

Đầu ra:

1
1
1
0
1
2
2

6

Một awkcách tiếp cận khác (sẽ trả về -1 cho các dòng trống).

awk -F'[^N ]' '$0=NF-1""' infile

Hoặc phức tạp, nó sẽ trả về -1 trên các dòng trống, 0 trên các dòng trắng (Tab / Spaces).

awk -F'[^N \t]+' '$0=NF-1""' infile

sẽ in -1cho các dòng trống ... nhưng sau đó có thể mong muốn phân biệt dòng được tạo thành chỉ bằng N / dấu cách và dòng trống ...
Sundeep

1
@Sundeep Vâng, đúng vậy. cũng xem bản cập nhật của tôi trong đó các dòng chỉ chứa Tab hoặc Spaces để biểu thị là 0
αғsнι

5
  1. trvà tập lệnh shell POSIX :

    tr -d 'N ' < file | while read x ; do echo ${#x} ; done
    
  2. bash, kshzsh:

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    

1
có thể sử dụng awk '{print length()}'để tránh vòng lặp vỏ chậm hơn .. nhưng sau đó người ta có thể làm tất cả với chính awk ...
Sundeep

@Sundeep, Nó là sự thật, ( nếu cả hai đều bắt đầu cùng một lúc), mà awkvòng lặp nhanh hơn so với vỏ lặp. Nhưng lớp vỏ luôn nằm trong bộ nhớ và awkcó thể không - khi awkchưa được tải hoặc bị tráo đổi, chi phí tải nó, ( mất thời gian ), có thể lớn hơn lợi thế của việc chạy awk- đặc biệt là nhỏ vòng. Trong những trường hợp như vậy, ( ví dụ trường hợp này), awkcó thể chậm hơn .
agc

tốt, tôi chắc chắn không lo lắng về thời gian cho những thứ nhỏ nhặt ... xem unix.stackexchange.com/questions/169716/ mẹo
Sundeep

1
@Sundeep, tôi làm lo lắng. Cách đây một thời gian, tôi thường sử dụng các bản phát hành Linux dựa trên đĩa mềm , có thể chạy hết đĩa mềm, trong một vài meg ram. Không cần sử dụng awktrong tập lệnh shell có thể làm cho hệ thống thu thập dữ liệu như vậy trên tất cả bốn bộ. Nói chung: lực kéo trễ tương tự áp dụng cho các hệ thống trong phần sụn bị giới hạn hoặc bất kỳ hệ thống nào chịu tải nặng.
agc

1

Một sự kết hợp ngắn của trawk:

$ tr -d ' N' <file.in | awk '{ print length }'
1
1
1
0
1
2
2

Thao tác này sẽ xóa tất cả khoảng trắng Ns khỏi tệp đầu vào và awkchỉ in độ dài của mỗi dòng.


0

Một cách dễ dàng khác là làm điều đó trong python, được cài đặt sẵn trong hầu hết các môi trường unix. Thả mã sau vào tệp .py:

with open('geno') as f:
    for line in f:
        count = 0
        for word in line.split():
            if word != 'N':
                count += 1
        print(count)

Và sau đó làm:

python file.py

Từ thiết bị đầu cuối của bạn. Những gì ở trên là:

  • cho mỗi dòng trong một tệp có tên "geno"
  • đặt bộ đếm thành 0 và tăng nó mỗi lần chúng ta tìm thấy một giá trị! = 'N'
  • khi đến cuối dòng hiện tại, in bộ đếm và đi đến dòng tiếp theo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.