2011-12-19 60 views
18

Tin hay không, tôi không thể tìm thấy câu trả lời cho những gì tôi nghĩ sẽ là câu hỏi rất cơ bản này.lặp qua các ký tự trong chuỗi đầu vào bằng cách sử dụng awk

Khi bị lúng túng, làm cách nào tôi có thể lặp lại ký tự chuỗi đầu vào theo ký tự? Giả sử tôi chỉ muốn in chúng ra. Có một mảng tôi có thể truy cập? Hay tôi cần sử dụng chất nền?

Về cơ bản, một cái gì đó như:

echo "here is a string" | awk ' 
{ for(i=0; i<[length of input string]; i++) 
    printf [value at index i in array x]; 
}' 

Thẳng thắn mà nói, tôi cảm thấy xấu hổ.

Trả lời

32

Bạn có thể chuyển đổi một chuỗi thành một mảng sử dụng split:

echo "here is a string" | awk ' 
{ 
    split($0, chars, "") 
    for (i=1; i <= length($0); i++) { 
    printf("%s\n", chars[i]) 
    } 
}' 

này in các nhân vật theo chiều dọc, mỗi dòng một.

+0

thực sự, length() là một tiện ích mở rộng gawk AFAIK, nó không hoạt động trên nền tảng tinh khiết awk http://stackoverflow.com/questions/14720898/illegal-reference-to-an-array-in-awk-i- am-having-trouble-figuring-out-awk – vaxquis

+0

@vaxquis Tôi không chắc chắn những gì bạn có nghĩa là bởi "tinh khiết" awk, nhưng 'chiều dài' là trong POSIX. Phần mở rộng gawk là áp dụng cho mảng thay vì chuỗi. May mắn thay, chúng ta chỉ có thể chuyển 'length (chars)' thành 'length ($ 0)'. –

+2

"tinh khiết" awk trong ý nghĩa của "không phải bất kỳ awk mở rộng" ... và có, tôi có nghĩa là cách sử dụng này của chiều dài(); Ngoài ra, bạn có thể sử dụng "len = split (...)" và sau đó "i <= len" với cùng một kết quả. – vaxquis

0

nếu bạn có gawk:

awk '$0=gensub(/(.)/,"\\1\n","g")' file 

kiểm tra:

kent$ echo "I am a String"|awk '$0=gensub(/(.)/,"\\1\n","g")' 
I 

a 
m 

a 

S 
t 
r 
i 
n 
g 
+0

là có một cách để làm điều gì đó với mỗi nhân vật bằng cách sử dụng phương pháp này hoặc là nó chỉ định dạng lại chuỗi? –

+1

nó có thể "làm điều gì đó với mỗi char". nhưng nó phụ thuộc vào "cái gì" " – Kent

13

Theo mặc định trong awk các Field Separator (FS)space hoặc tabs. Vì bạn đã đề cập bạn muốn lặp qua từng ký tự và không phải từ, chúng tôi sẽ phải xác định lại FS thành không có gì. Một cái gì đó như thế này -

[jaypal:~/Temp] echo "here is a string" | awk -v FS="" ' 
{for (i=1;i<=NF;i++) printf "Character "i": " $i"\n"}' 
Character 1: h 
Character 2: e 
Character 3: r 
Character 4: e 
Character 5: 
Character 6: i 
Character 7: s 
Character 8: 
Character 9: a 
Character 10: 
Character 11: s 
Character 12: t 
Character 13: r 
Character 14: i 
Character 15: n 
Character 16: g 
+0

AFAIK bạn có thể đặt FS =" "trong mã, không cần sử dụng nó bên ngoài ... – vaxquis

+0

hm. trên thực tế, nó hoạt động khi FS được đặt trong mã, nhưng theo một cách khác bit ... (ví dụ: dòng đầu tiên không được phân tích cú pháp) Bất kỳ ý tưởng nào tại sao? – vaxquis

+2

Đó là vì dòng đầu tiên đã được đọc trước đó với FS mặc định. –

5

Không phải tất cả triển khai awk đều hỗ trợ các giải pháp trên. Trong trường hợp đó bạn có thể sử dụng substr:

echo here is a string | awk '{ 
    for (i=0; ++i <= length($0);) 
    printf "%s\n", substr($0, i, 1) 
    }' 

T.B. Trong một số awk triển khai chiều dài không có đối số mặc định là $ 0, ví dụ dàichiều dài ($ 0) là tương đương.

Các vấn đề liên quan