Thêm Cột giá trị trong tệp được phân tách bằng tab


17

Làm cách nào tôi có thể thêm Cột giá trị trong tệp có số lượng hàng nhất định. Tôi có một tập tin đầu vào như thế này:

Tập tin đầu vào:

SPATA17 1   217947738
LYPLAL1 1   219383905
FAM47E  4   77192838
SHROOM3 4   77660162
SHROOM3 4   77660731
SHROOM3 4   77662248

Tập tin đầu ra:

SPATA17 1   217947738 file1
LYPLAL1 1   219383905 file1
FAM47E  4   77192838  file1
SHROOM3 4   77660162  file1
SHROOM3 4   77660731  file1
SHROOM3 4   77662248  file1

Trong trường hợp này, tôi muốn thêm Cột giá trị, tối đa số lượng hàng trong tệp. Giá trị vẫn nhất quán, chẳng hạn như "file1".

Lý do là tôi có 100 tệp đó. Tôi không muốn mở từng tệp và dán một cột. Cũng có cách nào để tự động hóa điều này, bằng cách vào một thư mục và thêm một cột các giá trị. Giá trị đến từ tên tệp, phải được thêm vào trong mỗi hàng của tệp trong cột cuối cùng / đầu tiên.

Câu trả lời:


22

Bạn có thể sử dụng vòng lặp một lớp như thế này:

for f in file1 file2 file3; do sed -i "s/$/\t$f/" $f; done

Đối với mỗi tệp trong danh sách, điều này sẽ sử dụng sedđể nối vào cuối mỗi dòng một tab và tên tệp.

Giải trình:

  • Sử dụng -icờ với sedđể thực hiện thay thế tại chỗ, ghi đè tệp
  • Thực hiện thay thế bằng s/PATTERN/REPLACEMENT/. Trong ví dụ này THỰC HIỆN là $, cuối dòng và REPLACEMENT là \t(= a TAB) và $flà tên tệp, từ biến vòng lặp. Các s///lệnh nằm trong hai dấu ngoặc kép để vỏ có thể mở rộng các biến.

Mã hoạt động. Bạn có thể giải thích nội dung trong dấu ngoặc kép?
Ron

Giống như "awk" được sử dụng trong khi làm việc với các cột, 'sed' cũng được sử dụng cho các tình huống tương tự. Tôi là người mới sử dụng 'awk' và 'sed'.
Ron

@Ron sedlà thiết thực nhất để thay thế mẫu và tiết kiệm tại chỗ. Đối với yêu cầu lưu tệp của bạn, đây là một tùy chọn tương đối thuận tiện. Nếu bạn không cần phải ghi lại vào cùng một tệp mà bạn đang xử lý, thì việc xử lý awkthường dễ dàng hơn nhiều.
janos

Cá nhân, tôi bị tăng gấp ba lần bởi awkcác dấu tách trường đầu vào / đầu ra quá thường xuyên, và vì vậy hãy cố gắng tránh sử dụng nó bất cứ khi nào có thể, làm cho sedhấp dẫn hơn.
dùng5359531

11

Hãy đến tại sao các bạn đề xuất những công cụ mạnh mẽ đó khi có pastelệnh!

$ cat a
A
B
C
D
$ cat b
1
2
3
4
$ paste a b
A   1
B   2
C   3
D   4

Với một chút mánh khóe, bạn có thể sử dụng pastecho mục đích của OP. Tuy nhiên, nó sẽ không thay thế các tập tin tại chỗ:

for f in file1 file2 file3; do 
    paste $f <(yes $f | head -n $(cat $f | wc -l)) > $f.new
done

Điều này sẽ dán tên tệp tương ứng làm cột cuối cùng của mỗi tệp vào tệp mới filename.new


Cảm ơn! pastechắc chắn là một viên ngọc ẩn.
neu242

10

Bạn có thể sử dụng awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...

Vì mỗi tệp có tên khác nhau, vì vậy tôi phải làm điều này 100 lần. Có cách nào để thực hiện một lần không?
Ron

Không, FILENAMElà một biến trong awk, nó mở rộng thành tên tệp hiện tại awkđang xử lý. Bạn chỉ cần làm một, cung cấp tất cả các tập tin awk.
cuonglm

ok, nhưng làm thế nào để hướng đầu ra vào một tệp mới, của mỗi tệp? awk có lưu trữ từng tệp trong khi xử lý không?
Ron

Nếu bạn có GNU awk 4.1.0hoặc sau này, bạn có thể sử dụng -iđể chỉnh sửa tại chỗ. Nếu không, bạn nên chuyển hướng awkouput sang tệp tạm thời, sau đó sử dụng grepđể trích xuất dòng từ mỗi tệp.
cuonglm

Vâng, bạn có thể làmfor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
fedorqui
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.