Thay thế khoảng trắng bằng các tab trong linux


98

Làm cách nào để thay thế khoảng trắng bằng các tab trong linux trong một tệp văn bản nhất định?

Câu trả lời:


168

Sử dụng chương trình unxpand (1)


UNEXPAND(1)                      User Commands                     UNEXPAND(1)

NAME
       unexpand - convert spaces to tabs

SYNOPSIS
       unexpand [OPTION]... [FILE]...

DESCRIPTION
       Convert  blanks in each FILE to tabs, writing to standard output.  With
       no FILE, or when FILE is -, read standard input.

       Mandatory arguments to long options are  mandatory  for  short  options
       too.

       -a, --all
              convert all blanks, instead of just initial blanks

       --first-only
              convert only leading sequences of blanks (overrides -a)

       -t, --tabs=N
              have tabs N characters apart instead of 8 (enables -a)

       -t, --tabs=LIST
              use comma separated LIST of tab positions (enables -a)

       --help display this help and exit

       --version
              output version information and exit
. . .
STANDARDS
       The expand and unexpand utilities conform to IEEE Std 1003.1-2001
       (``POSIX.1'').

4
Woah, không bao giờ biết mở rộng / không mở rộng tồn tại. Tôi đã cố gắng làm điều ngược lại và mở rộng là hoàn hảo thay vì phải làm rối tung với trhoặc sed.
Ibrahim

4
Đối với bản ghi, mở rộng / không mở rộng là các tiện ích tiêu chuẩn .
kojiro

4
Tuyệt đến nỗi đây là tiêu chuẩn. Tôi yêu triết lý UNIX . Sẽ rất tốt nếu nó có thể hoạt động tại chỗ.
Matthew Flaschen

3
Tôi không nghĩ rằng unxpand sẽ hoạt động ở đây .. nó chỉ chuyển đổi các khoảng trắng ở đầu và chỉ với hai hoặc nhiều khoảng trắng .. xem tại đây: list.gnu.org/archive/html/bug-textutils/2001-01/msg00025.html
olala

13
Chỉ cần lưu ý - unxpand sẽ không chuyển đổi một khoảng trắng thành tab. Nếu bạn cần chuyển đổi một cách mù quáng tất cả các ký tự 0x20 thành một tab duy nhất, bạn cần một công cụ khác.
Steve S.

44

Tôi nghĩ bạn có thể thử với awk

awk -v OFS="\t" '$1=$1' file1

hoặc SED nếu bạn mua trước

sed 's/[:blank:]+/,/g' thefile.txt > the_modified_copy.txt

hoặc thậm chí tr

tr -s '\t' < thefile.txt | tr '\t' ' ' > the_modified_copy.txt

hoặc một phiên bản đơn giản của giải pháp tr do Sam Bisbee đưa ra

tr ' ' \\t < someFile > someFile

4
Trong ví dụ về sed của bạn, các phương pháp hay nhất quy định rằng bạn sử dụng tr để thay thế các ký tự đơn trên sed vì lý do hiệu quả / tốc độ. Ngoài ra, tr ví dụ là dễ dàng hơn nhiều theo cách này:tr ' ' \\t < someFile > someFile
Sam Bisbee

2
Tất nhiên, tr có hiệu suất tốt hơn sed, nhưng lý do chính mà tôi yêu Unix là có nhiều cách để làm điều gì đó. Nếu bạn định thực hiện việc thay thế này nhiều lần, bạn sẽ tìm kiếm một giải pháp có hiệu suất tốt, nhưng nếu bạn chỉ thực hiện nó một lần, bạn sẽ tìm kiếm một giải pháp liên quan đến một lệnh khiến bạn cảm thấy có thể hiểu được.
Jonathan

2
lập luận. Tôi đã phải sử dụng thử và sai để làm cho sed hoạt động. Tôi không biết tại sao tôi phải thoát khỏi dấu cộng như thế này:ls -l | sed "s/ \+/ /g"
Jess

Với awk -v OFS="\t" '$1=$1' file1tôi nhận thấy rằng nếu bạn có một dòng bắt đầu bằng số 0 (ví dụ 0 1 2), thì dòng đó sẽ bị bỏ qua khỏi kết quả.
Nikola Novak

@Jess Bạn đã tìm thấy "cú pháp mặc định đúng" regex. Theo mặc định, sed coi dấu cộng đơn (không thoát) là ký tự đơn giản. Điều này cũng đúng với một số ký tự khác như '?', ... Bạn có thể tìm thêm thông tin tại đây: gnu.org/software/sed/manual/html_node/… . Bạn có thể tìm thấy chi tiết cú pháp tương tự tại đây (lưu ý rằng đây là người dùng cho grep, không phải sed): gnu.org/software/grep/manual/grep.html#Basic-vs-Extended .
Victor Yarema

11

Sử dụng Perl :

perl -p -i -e 's/ /\t/g' file.txt

3
Gặp sự cố tương tự khi thay thế các khoảng trắng liên tiếp bằng một tab. Perl làm việc chỉ với việc thêm dấu '+' vào regexp.
Todd

Mặc dù, tất nhiên, tôi muốn làm điều ngược lại: các tab chuyển đổi đến hai chỗ:perl -p -i -e 's/\t/ /g' *.java
TimP

Tôi có thể làm điều này một cách đệ quy không?
Aaron Franke

9

lệnh tr tốt hơn :

tr [:blank:] \\t

Điều này sẽ làm sạch đầu ra của say, giải nén -l , để xử lý thêm với grep, cut, v.v.

ví dụ,

unzip -l some-jars-and-textfiles.zip | tr [:blank:] \\t | cut -f 5 | grep jar

Tôi không cần phải sử dụng dấu ngoặc kép để làm cho nó làm việc:tr [:blank:] \\t
Ömer Một

3

Tải xuống và chạy tập lệnh sau để chuyển đổi đệ quy tab mềm thành tab cứng trong tệp văn bản thuần túy.

Đặt và thực thi tập lệnh từ bên trong thư mục chứa các tệp văn bản thuần túy.

#!/bin/bash

find . -type f -and -not -path './.git/*' -exec grep -Iq . {} \; -and -print | while read -r file; do {
    echo "Converting... "$file"";
    data=$(unexpand --first-only -t 4 "$file");
    rm "$file";
    echo "$data" > "$file";
}; done;

2

Lệnh ví dụ để chuyển đổi từng tệp .js dưới dir hiện tại thành các tab (chỉ các khoảng trắng ở đầu mới được chuyển đổi):

find . -name "*.js" -exec bash -c 'unexpand -t 4 --first-only "$0" > /tmp/totabbuff && mv /tmp/totabbuff "$0"' {} \;

Đã kiểm tra trong cygwin trên windows 7.
arkod

1

Bạn cũng có thể sử dụng astyle. Tôi thấy nó khá hữu ích và nó cũng có một số tùy chọn:

Tab and Bracket Options:
   If  no  indentation  option is set, the default option of 4 spaces will be used. Equivalent to -s4 --indent=spaces=4.  If no brackets option is set, the
   brackets will not be changed.

   --indent=spaces, --indent=spaces=#, -s, -s#
          Indent using # spaces per indent. Between 1 to 20.  Not specifying # will result in a default of 4 spaces per indent.

   --indent=tab, --indent=tab=#, -t, -t#
          Indent using tab characters, assuming that each tab is # spaces long.  Between 1 and 20. Not specifying # will result in a default assumption  of
          4 spaces per tab.`

0

Nếu bạn đang nói về việc thay thế tất cả các khoảng trắng liên tiếp trên một dòng bằng một tab thì tr -s '[:blank:]' '\t'.

[root@sysresccd /run/archiso/img_dev]# sfdisk -l -q -o Device,Start /dev/sda
Device         Start
/dev/sda1       2048
/dev/sda2     411648
/dev/sda3    2508800
/dev/sda4   10639360
/dev/sda5   75307008
/dev/sda6   96278528
/dev/sda7  115809778
[root@sysresccd /run/archiso/img_dev]# sfdisk -l -q -o Device,Start /dev/sda | tr -s '[:blank:]' '\t'
Device  Start
/dev/sda1       2048
/dev/sda2       411648
/dev/sda3       2508800
/dev/sda4       10639360
/dev/sda5       75307008
/dev/sda6       96278528
/dev/sda7       115809778

Nếu bạn đang nói về việc thay thế tất cả khoảng trắng (ví dụ: khoảng trắng, tab, dòng mới, v.v.) thì tr -s '[:space:]'.

[root@sysresccd /run/archiso/img_dev]# sfdisk -l -q -o Device,Start /dev/sda | tr -s '[:space:]' '\t'
Device  Start   /dev/sda1       2048    /dev/sda2       411648  /dev/sda3       2508800 /dev/sda4       10639360        /dev/sda5       75307008        /dev/sda6     96278528        /dev/sda7       115809778  

Nếu bạn đang nói về việc sửa một tệp bị hỏng tab thì hãy sử dụng expandunexpand như đã đề cập trong các câu trả lời khác.


0

Sử dụng sed :

T=$(printf "\t")
sed "s/[[:blank:]]\+/$T/g"

hoặc là

sed "s/[[:space:]]\+/$T/g"

-1

Điều này sẽ thay thế các khoảng trắng liên tiếp bằng một khoảng trắng (nhưng không phải tab).

tr -s '[:blank:]'

Điều này sẽ thay thế các khoảng trắng liên tiếp bằng một tab.

tr -s '[:blank:]' '\t'

Trên thực tế, với -cnó thay thế các ký tự liên tiếp không phải là dấu cách.
wingsubmariner

1
Câu hỏi là về các tab, đây không phải là câu trả lời.
Matthew Đọc
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.