Thêm một chuỗi tiền tố vào đầu mỗi dòng


333

Tôi có một tập tin như dưới đây:

line1
line2
line3

Và tôi muốn có được:

prefixline1
prefixline2
prefixline3

Tôi có thể viết một tập lệnh Ruby, nhưng sẽ tốt hơn nếu tôi không cần.

prefixsẽ chứa /. Đó là một con đường /opt/workdir/chẳng hạn.

Câu trả lời:


525
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

Nếu prefixcó chứa /, bạn có thể sử dụng bất kỳ ký tự nào khác không có trong prefixhoặc thoát lệnh /, để sedlệnh trở thành

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'

1
@benjamin, tôi đã nâng cao câu trả lời của bạn, tuy nhiên, tôi thích sedcác tác vụ nhẹ như thế này. Nếu "tiền tố" được biết đến, rất dễ dàng để chọn một ký tự không phải từ "tiền tố".
Alok Singhal

1
Đừng quên bạn cũng có thể sử dụng sedtrong một đường ống, ví dụ foo | sed -e 's/^/x /' | bar.
zigg

1
@Dataman ngầu. Một cách khác sẽ là sed -e '2,$s/^/prefix/'.
Alok Singhal

1
@BinChen thoát /tương tự \/(trong chuỗi trích dẫn đơn) hoặc \\/(trong chuỗi trích dẫn kép)

8
Sử dụng sed -e 's/$/postfix/' filenếu bạn muốn thêm chuỗi vào cuối mỗi dòng.
Brian

121
awk '$0="prefix"$0' file > new_file

Với Perl (thay thế tại chỗ):

perl -pi 's/^/prefix/' file

8
Với đường ống / luồng hoặc biến:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner

2
Với một tệp lớn (12 G), awkbáo cáo awk: out of memory in readrec 1 source line number 1, nhưng giải pháp sedhoàn thành thành công.
JRM

33

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

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

  2. s thay thế

  3. x lưu và đóng


1
Đối với tôi, tôi chỉ mở tệp bằng vim và gõ :%s/^/prefix/, vì chiến lược này kết thúc có ích trong nhiều tình huống
Frank Bryce

23

Nếu tiền tố của bạn hơi phức tạp, chỉ cần đặt nó vào một biến:

prefix=path/to/file/

Sau đó, bạn chuyển biến đó và để awk xử lý nó:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt


6

Sử dụng vỏ:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file

5

Đây là một giải pháp oneliner cực kỳ dễ đọc bằng cách sử dụng tslệnh từ moreutils

$ cat file | ts prefix | tr -d ' '

Và làm thế nào nó bắt nguồn từng bước:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3

'ts' không được cài đặt theo mặc định trên nhiều bản phân phối Linux. Ngoài ra, bỏ phiếu vì dấu "tr -d ''" trong câu trả lời này sẽ xóa tất cả các khoảng trắng khỏi các dòng, không chỉ là khoảng trắng được thêm bởi 'ts'
Tim Bird

3

Mặc dù tôi không nghĩ rằng pierr có mối quan tâm này, tôi cần một giải pháp sẽ không trì hoãn đầu ra từ "đuôi" trực tiếp của tệp, vì tôi muốn theo dõi một số nhật ký cảnh báo đồng thời, tiền tố mỗi dòng với tên của nhật ký tương ứng .

Thật không may, sed, cắt, vv đã giới thiệu quá nhiều bộ đệm và khiến tôi không nhìn thấy các dòng mới nhất. Đề nghị sử dụng -stùy chọn của Steven Penny nlrất hấp dẫn và thử nghiệm đã chứng minh rằng nó không giới thiệu bộ đệm không mong muốn liên quan đến tôi.

Tuy nhiên, có một số vấn đề khi sử dụng nlliên quan đến mong muốn loại bỏ các số dòng không mong muốn (ngay cả khi bạn không quan tâm đến tính thẩm mỹ của nó, có thể có trường hợp sử dụng các cột phụ sẽ không mong muốn). Đầu tiên, sử dụng "cắt" để loại bỏ các con số giới thiệu lại vấn đề đệm, do đó, nó phá hỏng giải pháp. Thứ hai, sử dụng "-w1" không giúp ích gì, vì điều này KHÔNG giới hạn số dòng trong một cột - nó chỉ rộng hơn khi cần nhiều chữ số hơn.

Sẽ không hay nếu bạn muốn chụp cái này ở nơi khác, nhưng vì đó chính xác là những gì tôi không cần làm (mọi thứ đã được ghi vào tệp nhật ký rồi, tôi chỉ muốn xem nhiều lần trong thời gian thực), tốt nhất cách để mất số dòng và chỉ có tiền tố của tôi là bắt đầu -schuỗi bằng trả về vận chuyển (CR hoặc ^ M hoặc Ctrl-M). Ví dụ:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}

1
sử dụng -utùy chọn để sed để tránh đệm.
Bryan Larsen

2
Đệm có thể được tắt với unbuffer / stdbuf, xem unix.stackexchange.com/q/25372/6205
myroslav

2

Sử dụng ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

Điều này thay thế, cho mỗi dòng ( ,), bắt đầu của dòng ( ^) với prefix. wqtiết kiệm và thoát ra.

Nếu chuỗi thay thế chứa dấu gạch chéo, chúng ta có thể sử dụng một dấu phân cách khác để sthay thế:

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

Tôi đã trích dẫn dấu phân cách doc-doc EOE("end of ed") để ngăn mở rộng tham số. Trong ví dụ này, nó cũng hoạt động không được trích dẫn, nhưng đó là cách tốt để ngăn chặn những điều bất ngờ nếu bạn có một $tập lệnh ed.


2

Sử dụng & (toàn bộ phần đầu vào được khớp với mẫu hình mẫu):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

HOẶC sử dụng tài liệu tham khảo trở lại:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt

2
  1. Bạn cũng có thể đạt được điều này bằng cách sử dụng kỹ thuật backreference

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Bạn cũng có thể sử dụng với awk như thế này

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    

1

Đây là một ví dụ được bao bọc bằng cách sử dụng cách sedtiếp cận từ câu trả lời này :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

tiền tố_lines

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE

2
Điều này sẽ không hoạt động nếu PREFIXchứa bất kỳ ký tự đặc biệt nào để quyến rũ như dấu gạch chéo.
josch

Điểm hay ... Nếu bạn thấy bạn sử dụng dấu gạch chéo, bạn có thể sử dụng một dấu phân cách khác với phần sed, như chi tiết ở đây , cho phép bạn sử dụng nó trong các tìm kiếm. Ký tự đặc biệt sed khác có thể được đưa vào bằng cách thoát với một dấu gạch chéo, ví dụ:prefix_lines \*
Brad Parks

0

Đối với những người trên hệ thống BSD / OSX, tiện ích được gọi là lamviết tắt của laminate. lam -s prefix filesẽ làm những gì bạn muốn. Tôi sử dụng nó trong đường ống, ví dụ:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... sẽ tìm thấy tất cả các tệp, thực thi lam trên mỗi tệp, cung cấp cho mỗi tệp một tiền tố của tên tệp riêng của nó. (Và bơm đầu ra cho fzf để tìm kiếm.)


Tôi đang dùng Ubuntu 19.10 và không có lệnh nào như vậy
nafg

Bạn nói đúng, có vẻ đây là lệnh chỉ BSD. POSIX đã thay thế nó bằng dán, nhưng dán không có tính năng thêm chuỗi phân tách đầy đủ. Tôi sẽ cập nhật câu trả lời của tôi.
Ray
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.