1

Topic: Dùng awk, sed để thay thế string tại line nhất định?

Chào mọi người,

Mình có cấu trúc file input thế này:
input.txt

4
Frame1
Na 1 2 3
O 4 6 5
O 5 1 3
H 4 2 3
4 
Frame2
Na 1 2 3
O 4 6 5
O 5 1 3
H 4 2 3
......
4
frame5000
Na 1 2 3
O 4 6 5
O 5 1 3
H 4 2 3

Giải thích: Tổng số có 5000 frame, một frame thì có 4 hàng, trong hàng thì cột đầu tiên ghi ký hiệu các nguyên tố hoá học.

Giờ em muốn, thay đổi cột đầu tiên từ hàng thứ x đến hàng thứ y thành ký hiệu khác. 

Ví dụ thay đổi file input trên với hàng thứ 3 và 4, H-->H1, O-->O1 trong toàn bộ 5000 frame đó.
output.txt

4
Frame1
Na 1 2 3
O 4 6 5
O1 5 1 3
H1 4 2 3
4 
Frame2
Na 1 2 3
O 4 6 5
O1 5 1 3
H1 4 2 3
.....
4
frame5000
Na 1 2 3
O   4 6 5
O1 5 1 3
H1  4 2 3

Hy vọng mọi người hiểu vấn đề.
(Em có thể dùng python để xử lý từng hàng nhưng có thể tốc độ khá chậm khi file lớn.)
Em mong muốn dùng awk,sed, perl mà vẫn chưa nghĩ ra. Mong các cao thủ vào chỉ giáo.

Cảm ơn mọi người !

Last edited by hoctro (23/01/2010 02:17)

em la newbie, cac bac thong cam neu em hoi may cau hoi bi stupid nhe. smile

2

Re: Dùng awk, sed để thay thế string tại line nhất định?

Bất cứ lang nào cũng phải ... xử lý từng hàng cả smile Python mà chậm thì Perl cũng không nhanh hơn được.

"La photographie est une brève complicité entre la prévoyance et le hasard." John Stuart Mill

3

Re: Dùng awk, sed để thay thế string tại line nhất định?

Dùng python được thì cứ thế mà dùng thôi. Khi file lớn quá thì lưu ý tới bộ nhớ một chút, đừng để 1 string khoảng vài MB là ổn big_smile

4

Re: Dùng awk, sed để thay thế string tại line nhất định?

Bạn cho mình xem đoạn Python được không?

Bạn có thể dùng awk split ra:

awk '/Frame/{n++} {print > "Frame" n ".txt"}' input.txt

Replace rồi gộp lại:

for ((i=1; i<=5000; i++)) do sed -e '4s/O/O1/' -e '5s/H/H1/' Frame$i.txt >> output.txt; done

Không biết so với cách của bạn thì thế nào.

Last edited by quanta (28/01/2010 20:07)

To live is to Fight.

5

Re: Dùng awk, sed để thay thế string tại line nhất định?

# bài toán này có thể giải quyết hoàn tòan bằng awk do cấu trúc tập tin đã ổn
# thuật toán như sau
## duyệt qua từng dòng,
### nếu gặp Frame thì đặt bộ đếm dòng $frame_line = 0
### nếu không phải thì tăng biến $frame_line lên một đơn vị
### nếu $frame_line = 3 thì thực hiện thay thế, dùng printf và các biến $1, $2, $3, $4,... của awk

... important note: this isn't my signature ...

6

Re: Dùng awk, sed để thay thế string tại line nhất định?

quanta viết:

Bạn cho mình xem đoạn Python được không?

Bạn có thể dùng awk split ra:

awk '/Frame/{n++} {print > "Frame" n ".txt"}' input.txt

Replace rồi gộp lại:

for ((i=1; i<=5000; i++)) do sed -e '4s/O/O1/' -e '5s/H/H1/' Frame$i.txt >> output.txt; done

Không biết so với cách của bạn thì thế nào.

Đọc lại 'man sed' thì thấy có tuỳ chọn first~step nên có thể dùng:

$ sed -e '5~6s/O/O1/' -e '0~6s/H/H1/' input.txt
To live is to Fight.

7

Re: Dùng awk, sed để thay thế string tại line nhất định?

Cám ơn các bác, em dùng python hơi stupid nhưng work rồi, có vẻ cũng tốt không kém gì script awk, sed big_smile

#!/usr/bin/python

from sys import argv,exit
from string import rstrip
from Numeric import *

if len(argv) != 5:
  print "Usage: command trajectory.xyz total_atoms atomlist_file supfix"
  exit(1)

filename=argv[1]
total_atoms=int(argv[2])
#read atom file
atomlist_file=open(argv[3])
atomlist=(atomlist_file.read()).split()
atomlist_file.close()
#atomlist=[1,2,33,44]
#print atomlist
supfix=str(argv[4])
frame_order=001
infile=open(filename)
Aorder = 0
#Begin read
while 1:
   line=infile.readline()
   if not line:
    break
   print line.rstrip()     
   line=infile.readline()     
   print line.rstrip()
   Aorder = 0
   for i in range(0,total_atoms):
     line=infile.readline()     
     Aorder=Aorder+1
     if str(Aorder) not in atomlist:
        print line.rstrip()
     else:
      f=line.split()
      Aname=str(f[0])
      x=float(f[1])    
      y=float(f[2])
      z=float(f[3])
      print  "%s   %8.5f %8.5f %8.5f"%(Aname+supfix, x, y, z)
   frame_order=frame_order+1  
   if not line :
     exit(1)
infile.close()
em la newbie, cac bac thong cam neu em hoi may cau hoi bi stupid nhe. smile