Câu hỏi Tìm và thay thế văn bản trong một tệp bằng lệnh


Làm cách nào để tìm và thay thế các từ cụ thể trong tệp văn bản bằng dòng lệnh?


437
2018-01-07 04:10


gốc


Có thể bạn quan tâm github.com/lucio-martinez/rch :-) - Lucio


Các câu trả lời:


sed -i 's/original/new/g' file.txt

Giải trình:

  • sed = Trình chỉnh sửa luồng
  • -i = tại chỗ (tức là lưu lại tệp gốc)
  • Chuỗi lệnh:

    • s = lệnh thay thế
    • original = một cụm từ thông dụng mô tả từ cần thay thế (hoặc chỉ chính từ đó)
    • new = văn bản để thay thế nó bằng
    • g = toàn cầu (tức là thay thế tất cả và không chỉ là lần xuất hiện đầu tiên)
  • file.txt = tên tệp


728
2018-01-07 04:23



@mcExchange Nếu cụ thể là / mà bạn cần phải khớp, bạn chỉ có thể sử dụng một số ký tự khác làm dấu phân cách (ví dụ: 's_old/text_new/text_g'). Nếu không, bạn có thể đặt \  trước bất kỳ $ * . [ \ ^ để có được nhân vật theo nghĩa đen. - cscarney
@BrianZ Theo như hệ thống tập tin là có liên quan đầu ra của sed là một tập tin mới có cùng tên. Đó là một trong những các lỗi thường được báo cáo không phải là lỗi - cscarney
Bạn có thể muốn s/\boriginal\b/new/g thay vì s/original/new/g (\b phù hợp ở một ranh giới từ) chỉ thay thế toàn bộ từ. - Chris Martin
Lệnh OSX sed -i '.bak' 's/original/new/g' file.txt cũng có thể chạy với phần mở rộng bằng 0 sed -i '' 's/original/new/g' file.txt, sẽ không tạo sao lưu. - Kirk
Người dùng MacOS sẽ phải thêm '' "sau -i làm tham số cho -i ed.gs/2016/01/26/os-x-sed-invalid-command-code để tệp sẽ bị ghi đè. - geoyws


Có một số cách khác nhau để thực hiện việc này. Một người đang sử dụng sed và Regex. SED là Trình chỉnh sửa luồng để lọc và chuyển văn bản. Một ví dụ là như sau:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

Một cách khác có thể có ý nghĩa hơn < strin và > strout là với ống!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog

26
2018-01-07 04:26



lưu ý cat trong cat file | sed '...' là không cần thiết. Bạn có thể nói trực tiếp sed '...' file. - fedorqui
Thật vậy, điều này có thể được giảm thêm: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly sẽ lấy tập tin yarly và thực hiện 2 thay đổi tại chỗ trong khi thực hiện sao lưu. Sử dụng time bash -c "$COMMAND" đến thời điểm nó cho thấy rằng phiên bản này nhanh hơn gấp 5 lần. - pbhj


Bạn có thể sử dụng chế độ Vim ở chế độ Ex:

ex -sc '%s/OLD/NEW/g|x' file
  1. % chọn tất cả các dòng

  2. s thay thế

  3. g thay thế tất cả các trường hợp trong mỗi dòng

  4. x viết nếu thay đổi đã được thực hiện (họ có) và thoát


15
2018-04-16 18:36





Thông qua lệnh gsub của awk,

awk '{gsub(/pattern/,"replacement")}' file

Thí dụ:

awk '{gsub(/1/,"0");}' file

Trong ví dụ trên, tất cả các số 1 được thay thế bằng 0 bất kể cột nằm ở đâu.


Nếu bạn muốn thực hiện thay thế trên một cột cụ thể thì hãy làm như thế này,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Thí dụ:

awk '{gsub(/1/,"0",$1);}' file

Nó thay thế 1 bằng 0 chỉ trên cột 1.

Thông qua Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar

14
2017-07-02 12:59



Tôi đã sử dụng thiết bị này trên thiết bị đầu cuối MacOS và không có gì ... - Jim


Có rất nhiều cách để đạt được nó. Tùy thuộc vào độ phức tạp của những gì người ta cố gắng đạt được với thay thế chuỗi và tùy thuộc vào các công cụ mà người dùng quen thuộc, một số phương pháp có thể được ưu tiên hơn những phương pháp khác.

Trong câu trả lời này tôi đang sử dụng đơn giản input.txt tệp mà bạn có thể sử dụng để kiểm tra tất cả các ví dụ được cung cấp tại đây. Nội dung tập tin:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BASH

Bash không thực sự có ý nghĩa đối với việc xử lý văn bản, nhưng các thay thế đơn giản có thể được thực hiện thông qua mở rộng tham số , đặc biệt ở đây chúng ta có thể sử dụng cấu trúc đơn giản ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Tập lệnh nhỏ này không thay thế tại chỗ, có nghĩa là bạn sẽ phải lưu văn bản mới vào tệp mới và loại bỏ tệp cũ hoặc mv new.txt old.txt

Lưu ý phụ: nếu bạn tò mò về lý do while IFS= read -r ; do ... done < input.txt được sử dụng, về cơ bản là cách đọc tập tin theo dòng của shell. Xem điều này để tham khảo.

AWK

AWK, là một tiện ích xử lý văn bản, khá thích hợp cho nhiệm vụ đó. Nó có thể thực hiện các thay thế đơn giản và nhiều thay thế nâng cao hơn dựa trên cụm từ thông dụng. Nó cung cấp hai chức năng: sub() và gsub(). Người đầu tiên chỉ thay thế lần xuất hiện đầu tiên, trong khi thứ hai - thay thế các lần xuất hiện trong toàn bộ chuỗi. Ví dụ, nếu chúng ta có chuỗi one potato two potato , đây sẽ là kết quả:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK có thể lấy một tệp đầu vào làm đối số, vì vậy hãy làm những việc tương tự với input.txt , sẽ dễ dàng:

awk '{sub(/blue/,"azure")}1' input.txt

Tùy thuộc vào phiên bản AWK bạn có, nó có thể hoặc có thể không có chỉnh sửa tại chỗ, do đó thực hành thông thường là lưu và thay thế văn bản mới. Ví dụ một cái gì đó như thế này:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed là một trình soạn thảo dòng. Nó cũng sử dụng các biểu thức thông thường, nhưng đối với các thay thế đơn giản, nó đủ để làm:

sed 's/blue/azure/' input.txt

Điều tốt về công cụ này là công cụ có chỉnh sửa tại chỗ, bạn có thể bật -i cờ.

Perl

Perl là một công cụ khác thường được sử dụng để xử lý văn bản, nhưng nó là một ngôn ngữ mục đích chung, và được sử dụng trong mạng, quản trị hệ thống, ứng dụng dành cho máy tính để bàn và nhiều nơi khác. Nó mượn rất nhiều khái niệm / tính năng từ các ngôn ngữ khác như C, sed, awk và các ngôn ngữ khác. Thay thế đơn giản có thể được thực hiện như sau:

perl -pe 's/blue/azure/' input.txt

Giống như sed, perl cũng có cờ -i.

Python

Ngôn ngữ này rất linh hoạt và cũng được sử dụng trong nhiều ứng dụng khác nhau. Nó có rất nhiều chức năng để làm việc với các chuỗi, trong đó có replace(), vì vậy nếu bạn có biến như var="Hello World" , bạn có thể làm var.replace("Hello","Good Morning")

Cách đơn giản để đọc tập tin và thay thế chuỗi trong nó sẽ là như vậy:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Tuy nhiên, với Python, bạn cũng cần xuất ra tệp mới, mà bạn cũng có thể thực hiện từ bên trong tập lệnh. Ví dụ, đây là một cách đơn giản:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Kịch bản này sẽ được gọi với input.txt làm đối số dòng lệnh.

Python cũng có thể có các biểu thức chính quy, đặc biệt, re mô-đun, trong đó có re.sub() chức năng, có thể được sử dụng để thay thế nâng cao hơn.


12
2018-02-03 07:49





sed là Stream editor, trong đó bạn có thể sử dụng | (ống) để gửi luồng tiêu chuẩn (STDIN và STDOUT cụ thể) thông qua sed và thay đổi chúng theo cách lập trình trên bay, biến nó trở thành một công cụ hữu ích trong truyền thống triết học Unix; nhưng cũng có thể chỉnh sửa tệp trực tiếp, bằng cách sử dụng -i thông số được đề cập bên dưới.
Xem xét những điều sau:

sed -i -e 's/few/asd/g' hello.txt

s/ đã từng Substitute biểu thức tìm thấy few với asd:

Một số ít, dũng cảm.


Asd, dũng cảm.

/g viết tắt của "toàn cầu", có nghĩa là để làm điều này cho toàn bộ dòng. Nếu bạn rời khỏi /g (với s/few/asd/, luôn luôn cần phải có ba dấu gạch chéo không có vấn đề gì) và few xuất hiện hai lần trên cùng một dòng, chỉ lần đầu tiên few được thay đổi thành asd:

Vài người đàn ông, vài người phụ nữ, dũng cảm.


Những người đàn ông asd, vài người phụ nữ, dũng cảm.

Điều này hữu ích trong một số trường hợp, như thay đổi các ký tự đặc biệt khi bắt đầu các dòng (ví dụ, thay thế các ký tự lớn hơn một số người sử dụng để trích dẫn tài liệu trước đó trong các chuỗi email với một tab ngang trong khi để lại sự bất bình đẳng đại số được trích dẫn sau này trong dòng không bị ảnh hưởng), nhưng trong ví dụ của bạn, nơi bạn chỉ định bất cứ đâu  few xảy ra nó nên được thay thế, hãy chắc chắn rằng bạn có /g.

Hai tùy chọn sau (cờ) được kết hợp thành một, -ie:

-i tùy chọn được sử dụng để chỉnh sửa tôin nơi trên tập tin hello.txt.

-e tùy chọn cho biết expression / command để chạy, trong trường hợp này s/.

Lưu ý: Điều quan trọng là bạn sử dụng -i -e để tìm kiếm / thay thế. Nếu bạn làm -ie, bạn tạo bản sao lưu của mọi tệp bằng chữ 'e' được nối thêm.


6
2017-11-23 09:00





Bạn có thể làm như thế này:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Ví dụ: để thay thế tất cả các lần xuất hiện [logdir ',' '] (không có []) với [logdir', os.getcwd ()] trong tất cả các tệp được tạo thành từ lệnh, hãy làm:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

nơi [tensorboard / program.py] là tệp để tìm kiếm


0
2017-07-24 02:13



Chào. Sự lựa chọn dây của bạn (logdir', '' -> /logdir', os.getcwd()) làm cho câu trả lời này khó phân tích cú pháp. Ngoài ra, nó có giá trị xác định rằng câu trả lời của bạn đầu tiên đặt các tập tin để sử dụng sed trên, bởi vì nó không phải là một phần của câu hỏi. - mwfearnley
Xin chào, câu trả lời này vừa là tìm kiếm vừa thay thế tất cả nếu tìm thấy <văn bản cũ> trong tệp. - Nguyễn Tuấn Anh
Tôi chọn câu trả lời này cho tất cả họ sử dụng tensorboard trong keras, những người muốn thay đổi lệnh từ: tensorboard --logdir = '/ path / to / log / folder /' để sử dụng: tensorboard only, khi ở trong thư mục logs. no rât thuận tiện - Nguyễn Tuấn Anh