Tôi có một số tệp văn bản chứa một số cột được phân tách bằng nhiều khoảng trắng khác nhau, nhưng thay vào đó tôi cần một tab duy nhất làm dấu phân cách. Có thể làm trong Bash?
Tôi có một số tệp văn bản chứa một số cột được phân tách bằng nhiều khoảng trắng khác nhau, nhưng thay vào đó tôi cần một tab duy nhất làm dấu phân cách. Có thể làm trong Bash?
Câu trả lời:
Để chuyển đổi các chuỗi nhiều hơn một khoảng trắng thành một tab, nhưng để riêng các không gian riêng lẻ :
sed 's/ \+ /\t/g' inputfile > outputfile
Để làm điều này cho một số tệp:
for inputfile in *
do
sed 's/ \+ /\t/g' "$inputfile" > tmpfile && mv tmpfile "$inputfile"
done
hoặc là
for inputfile in *
do
sed -i.bak 's/ \+ /\t/g' "$inputfile"
done
hoặc là
find . -type f -exec sed -i.bak 's/ \+ /\t/g' {} \;
sed: -e expression #1, char 1: unknown command: `.'
find
cái ở phía dưới.
sed
không muốn có một khoảng trắng trước phần mở rộng sao lưu. Tôi đã chỉnh sửa câu trả lời của mình. Cảm ơn báo cáo.
Nếu nhân vật của bạn là nhiều tab, bạn cũng có thể sử dụng tr -s
:
-s, --squeeze-repeats replace each input sequence of a repeated character
that is listed in SET1 with a single occurrence
Ví dụ:
my_file.txt | tr -s " "
Tất cả các khoảng trắng sẽ trở thành một.
Bạn có thể sử dụng sed
để thay thế một số khoảng trắng bằng một tab.:
Ví dụ để thay thế một hoặc nhiều khoảng trắng bằng một tab:
cat spaced-file | sed 's/ \+/\t/g' > tabbed-file
Câu trả lời đơn giản nhất chỉ sử dụng bash
là:
while read -r col1 col2 col3 ...; do
echo -e "$col1\t$col2\t$col3..."
done <file
Nếu có một số lượng cột khác nhau, bạn có thể làm điều này, nhưng nó sẽ chỉ hoạt động bash
chứ không phải sh
:
while read -r -a cols; do
(
IFS=$'\t'
echo "${cols[*]}"
)
done <file
ví dụ
while read -r -a cols; do
(
IFS=$'\t'
echo "${cols[*]}"
)
done <<EOF
a b c
d e f
g h i
EOF
sản xuất:
a b c
d e f
g h i
(có một tab ở giữa mỗi cái, nhưng thật khó để nhìn thấy khi tôi dán nó ở đây)
Bạn cũng có thể làm điều đó bằng cách sử dụng sed
hoặc tr
, nhưng lưu ý rằng việc xử lý khoảng trống khi bắt đầu tạo ra kết quả khác nhau.
sed:
$ sed 's/ */\t/g' << EOF
a b c
d e f
g h i
EOF
a b c
d e f
g h i
tr:
$ tr -s ' ' '\t' <<EOF
a b c
d e f
g h i
EOF
a b c
d e f
g h i
perl -p -i -e 's/\s+/\t/g' *.txt
Đây là một giải pháp rất đơn giản:
sed -E 's/\s+/\t/g' your_file > new_file
Về cơ bản, sed hoạt động theo cách này (sed 's / old_potype / new_potype / g'). Trong trường hợp này, mẫu cũ là "\ s +" có nghĩa là tìm không gian "s" một hoặc nhiều lần "+" và dấu gạch chéo ngược "\" để diễn giải đó là biểu thức chính quy.
Mẫu mới là tab "\ t" được viết ở định dạng biểu thức chính quy và "g" được áp dụng thay thế cho tất cả các dòng "trên toàn cầu".