Nối hai biến với dấu gạch dưới


54

Tôi cần nối hai biến để tạo một tên tệp có dấu gạch dưới. Hãy gọi các biến của tôi $FILENAME$EXTENSIONnơi tên tệp được đọc từ một tệp.

FILENAME=Hello
EXTENSION=WORLD.txt

Hiện nay...

Tôi đã thử những điều sau đây mà không thành công:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION
NAME=$FILENAME\\_$EXTENSION

Tôi luôn luôn nhận được một số loại đầu ra kỳ lạ. Thường là dấu gạch dưới đầu tiên.

Tôi cần nó để được

echo $NAME
Hello_WORLD.txt

2
Có lẽ kịch bản của bạn chứa các ký tự trở về vận chuyển.
Stéphane Chazelas

Đúng đó là nó. : D
Rhyuk

Câu trả lời:


67

Bạn có thể sử dụng một cái gì đó như thế này:

NAME=$(echo ${FILENAME}_${EXTENSION})

Điều này cũng hoạt động:

NAME=${FILENAME}_${EXTENSION}

1
Vấn đề là tập tin mà tôi đã đọc TÊN. Định dạng Windows ... Giải pháp của bạn đã hoạt động rất tốt sau đó. Cảm ơn
Rhyuk

2
Lệnh đầu tiên xử lý giá trị của biến và việc sử dụng thay thế lệnh và echokhông thể giúp được. Lệnh thứ hai đã được đưa ra trong câu hỏi.
Gilles 'SO- ngừng trở nên xấu xa'

1
Đúng! Tôi thích nó. Điều này đã gây khó chịu cho tôi trong thời gian dài nhất. Cảm ơn giải pháp!
racl101

Điều này làm việc cho tôi. Khi tôi sử dụng '$ FILENAME_ $ EXTENSION', chỉ các giá trị của '$ EXTENSION' xuất hiện. Bạn có thể vui lòng giúp giải thích tại sao điều này xảy ra? Cảm ơn
Lei Hao

12

Của bạn:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION

tất cả đều ổn, vì vậy sẽ là:

NAME=${FILENAME}_${EXTENSION}
NAME=$FILENAME'_'$EXTENSION
NAME=$FILENAME\_$EXTENSION
NAME=$FILENAME"_$EXTENSION"

(nhưng chắc chắn không phải NAME=$(echo ${FILENAME}_${EXTENSION})nó sử dụngechocác split+globnhà điều hành ).

NAME=$FILENAME_$EXTENSION

sẽ giống như:

NAME=${FILENAME_}${EXTENSION}

as _(trái với \hoặc ') là một ký tự hợp lệ trong một tên biến.

Vấn đề của bạn là bạn đã có các dòng được phân tách bằng CRLF thay vì chỉ có LF, điều đó có nghĩa là những nội dung biến đó đã kết thúc bằng ký tự CR.

Ký tự CR, khi được ghi vào một thiết bị đầu cuối sẽ báo cho thiết bị đầu cuối di chuyển con trỏ đến đầu dòng. Vì vậy, Hello<CR>_WORLD.TXT<CR>khi được gửi đến một thiết bị đầu cuối sẽ hiển thị như _WORLD.TXT(ghi đè Hello).


1

Tôi đã chuyển sang sử dụng ${FILENAME}_${EXTENSION}cú pháp được đề cập ở trên.

Tôi đã từng sử dụng $()khi tôi cần nối hai biến với dấu gạch dưới. Ví dụ: $YYYYMMDD$()_$HHMMSSđể tạo một tên tệp chứa dấu thời gian theo định dạng của YYYYMMDD_HHMMSS. Giữa $()trả về không có gì và phá vỡ hai biến.

Tôi đã sử dụng timeđể đo các bài tập bằng $YYYYMMDD$()_$HHMMSSphương pháp và một số bài tập ở trên và tất cả chúng đều được báo cáo 0ms trên máy chủ cũ mà tôi đang sử dụng. Hiệu suất dường như không phải là một vấn đề.


Điều đó không trả lời câu hỏi. Bạn nên đưa ra một câu hỏi mới cho điều đó. $()không rẽ nhánh trong một vài vỏ (một số tối ưu hóa nó đi). Nó cũng chiếm quyền điều khiển cho một thứ mà nó không được thiết kế cho. ${x}_ylà những gì bạn muốn.
Stéphane Chazelas

Ý bạn là gì, đó không phải là câu trả lời. Đó không phải là một câu trả lời tuyệt vời, nhưng nó là một câu trả lời.
Scott

Chỉnh sửa để xóa bỏ sự mơ hồ.
dùng208145

0

Bạn nên sử dụng các biến trong chữ thường (đó là cách thực hành tốt nhất).
Vì vậy, tôi sẽ sử dụng tên tệp và phần mở rộng thay vì FILENAME và EXTENSION

Như bạn nói rằng tên tập tin của Wikipedia được đọc từ một tập tin, tôi sẽ cho rằng tập lệnh là:

read -r filename  <file.txt
extension=World.txt

Và bạn muốn nối cả hai biến $ filename và $ extension với dấu gạch dưới _.
Các ví dụ bạn cung cấp (ngoại trừ: không có gấp đôi \) hoạt động chính xác tại đây:

name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension

Như một số khác:

name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"

Vì vậy, vấn đề của bạn không phải là làm thế nào các biến dính vào nhau, mà là với nội dung của các vars. Có vẻ hợp lý khi nghĩ rằng điều này:

read -r filename  <file.txt

sẽ đọc trở lại vận chuyển kéo \rnếu đọc từ một tập tin windows.

Một giải pháp đơn giản (đối với ksh, bash, zsh) là xóa tất cả các ký tự điều khiển khỏi biến đọc:

filename=${filename//[[:cntrl:]]/}

Điều này có thể được mô phỏng với một giá trị có lợi nhuận vận chuyển:

$ filename=$'Hello\r'
$ echo "starting<$filename>end"
>endting<Hello                       ### note the return to the start of line.
$ echo "starting<${filename//[[:cntrl:]]/}>end"
starting<Hello>end

Hoặc, thay thế giá trị của filename:

$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end

Phần kết luận.

Vậy đây:

name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"

Sẽ nhận được giá trị chính xác namengay cả khi các vars khác chứa các ký tự điều khiển.



-2

Bạn cũng có thể sử dụng điều này: tách các lọ riêng biệt với khoảng trắng và nối chúng bằng cách sử dụng tr để loại bỏ khoảng trắng.

TableNameToCreate="MyTable"
# concatenation work is done here 
$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#Proof
echo "Var to create with var pasted as prefix to suffix
    $(echo "$TableNameToCreate _my_other_Info " | tr -d " ") 
. "

# create a new var
NewVar=$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#proof
echo "$NewVar"

(1) Câu hỏi này đã được trả lời đầy đủ hơn. (2) Câu trả lời của bạn sẽ làm gì nếu biến hiện có có các ký tự đặc biệt trong đó?
G-Man nói 'Phục hồi Monica'

Điều này không giải quyết vấn đề với biến chứa lợi nhuận vận chuyển. Nó cũng loại bỏ không gian, một cái gì đó có thể không muốn.
Kusalananda

@Kusalananda: Trên thực tế, trừ khi tôi nhìn ra thứ gì đó, chiếc xe này xử lý trở lại tốt; không gian là vấn đề duy nhất.
G-Man nói 'Phục hồi Monica'
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.