Làm thế nào để tôi đọc một biến từ một tập tin?


68

Tôi muốn chèn vào tập lệnh của mình một giá trị (chuỗi) mà tôi sẽ đọc từ tệp văn bản.

Ví dụ: thay vì:

echo "Enter your name"
read name

Tôi muốn đọc một chuỗi từ một tệp văn bản khác để trình thông dịch nên đọc chuỗi từ tệp chứ không phải đầu vào của người dùng.


1
Tập tin văn bản của bạn trông như thế nào? Là toàn bộ tập tin 1 biến hoặc chúng là KEY=VALUEcặp? Các giải pháp khá khác nhau (nếu là câu trả lời sau, câu trả lời của Takkat được áp dụng, câu trả lời của Radu trước đây)
kiri

1
@CiroSantilli nó không bị gạch chéo nếu nó được đăng bởi một người dùng khác, không có thứ gọi là "bản sao chéo trang". Điều duy nhất nên tránh là cùng một câu hỏi được hỏi bởi cùng một người dùng trên các trang web khác nhau.
terdon

Câu trả lời:


98

Để đọc các biến từ một tập tin, chúng ta có thể sử dụng lệnh sourcehoặc ..

Giả sử tập tin chứa dòng sau

MYVARIABLE="Any string"

sau đó chúng ta có thể nhập biến này bằng cách sử dụng

#!/bin/bash

source <filename>
echo $MYVARIABLE

16
Một lý do tại sao bạn có thể không muốn làm theo cách này là bởi vì bất cứ thứ gì trong đó <filename>sẽ được chạy trong vỏ của bạn, chẳng hạn như rm -rf /, có thể rất nguy hiểm.
Đánh dấu Ribau

3
Đến bữa tiệc muộn, nhưng, không, nó không xứng đáng được đánh dấu HOẶC là câu trả lời. Nguồn này cung cấp một tệp nguồn bash khác KHÔNG phải là những gì OP yêu cầu. Ông hỏi làm thế nào để đọc nội dung của một TẬP TIN vào một biến. KHÔNG làm thế nào để thực thi một tập lệnh khác mà đặt một biến . Câu trả lời đúng là câu dưới đây. tên = $ (mèo "$ tập tin").
HörmannHH

2
OTOH, đó là câu trả lời cho câu hỏi tôi đã hỏi google và google đã đưa tôi đến đây. Thời gian lạ nhỉ?
Michael Terry

1
Tuyệt vời cũng hoạt động cho nhiều biến! Điểm của @MarkRibau được hiểu nhưng tôi đoán rằng nếu bạn đúng tập tin trong một tập lệnh khác và chỉ cần vượt qua nó tốt và được kiểm soát.
madlymad

1
Bạn có thể sử dụng sedđể thêm localtừ khóa và làm cho tập lệnh an toàn hơn một chút và không làm hỏng phạm vi toàn cầu của bạn. Vì vậy, bên trong chức năng aa làm cat global_variables.sh | sed -e 's/^/local /' > local_variables.shvà sau đó sử dụng . ./local_variables.sh. Bất cứ điều gì bạn nhập vào hàm sẽ chỉ có sẵn trong hàm đó. Lưu ý rằng nó giả sử global_variables.shchỉ chứa một biến trên mỗi dòng.
Nux

55

Xem xét rằng bạn muốn tất cả nội dung của tệp văn bản của bạn được giữ trong biến của bạn, bạn có thể sử dụng:

#!/bin/bash

file="/path/to/filename" #the file where you keep your string name

name=$(cat "$file")        #the output of 'cat $file' is assigned to the $name variable

echo $name               #test

Hoặc, trong bash tinh khiết:

#!/bin/bash

file="/path/to/filename"     #the file where you keep your string name

read -d $'\x04' name < "$file" #the content of $file is redirected to stdin from where it is read out into the $name variable

echo $name                   #test

Tôi không muốn hiển thị biến, tôi muốn biến này phải được đọc bởi kịch bản để xử lý thêm. Tôi đã thử awk mà đọc từng dòng.
dùng208413

1
Ok, xóa đi echo $name . Tôi sử dụng nó chỉ để thử nghiệm. Tiếp theo, bạn có thể sử dụng $namebiến để xử lý thêm bất cứ nơi nào bạn muốn trong tập lệnh của mình.
Radu Rădeanu

Tôi không thể sử dụng nó ở bất cứ đâu, tập lệnh của tôi bởi vì tập lệnh dhe không biết giá trị của biến. Trong trường hợp của chúng tôi tên biến.
dùng208413

6
@ user208413 Giá trị của $namebiến là chuỗi từ tệp của bạn được gán bằng cat $filelệnh. Điều gì không rõ ràng hoặc quá khó hiểu?
Radu Rădeanu

1
Việc sử dụng $filebiến riêng biệt là không cần thiết nếu bạn chỉ sử dụng một lần để tải $namebiến đó, chỉ cần sử dụngcat /path/to/file
kiri

11

Từ trong tập lệnh của bạn, bạn có thể làm điều này:

read name < file_containing _the_answer

Bạn thậm chí có thể làm điều này nhiều lần, ví dụ như trong một vòng lặp

while read LINE; do echo "$LINE"; done < file_containing_multiple_lines

hoặc cho một tệp có nhiều mục trên mỗi dòng. . . grep -v ^ # file | trong khi đọc abc; làm tiếng vang a = $ ab = $ bc = $ c; xong
gaoithe

7

Một cách khác để làm điều này là chỉ chuyển hướng đầu vào tiêu chuẩn vào tệp của bạn, nơi bạn có tất cả đầu vào của người dùng theo thứ tự mà chương trình mong đợi. Ví dụ, với chương trình (được gọi script.sh)

#!/bin/bash
echo "Enter your name:"
read name
echo "...and now your age:"
read age

# example of how to use the values now stored in variables $name and $age
echo "Hello $name. You're $age years old, right?"

và tệp đầu vào (được gọi input.in)

Tomas
26

bạn có thể chạy nó từ thiết bị đầu cuối theo một trong hai cách sau:

$ cat input.in | ./script.sh
$ ./script.sh < input.in

và nó sẽ tương đương với việc chỉ chạy tập lệnh và nhập dữ liệu theo cách thủ công - nó sẽ in dòng "Xin chào Tomas. Bạn 26 tuổi, phải không?".

Như Radu Rădeanu đã đã gợi ý , bạn có thể sử dụng cattrong kịch bản của bạn đọc nội dung của một tập tin vào một avariable - trong trường hợp đó, bạn cần mỗi tập tin có chứa chỉ một dòng, chỉ với những giá trị mà bạn muốn cho rằng biến cụ thể. Trong ví dụ trên, bạn muốn chia tập tin đầu vào thành một với tên (ví dụ name.in) và một với tuổi (ví dụ age.in), và thay đổi read nameread agedòng để name=$(cat name.in)age=$(cat age.in)tương ứng.


Tôi có đoạn script sau: vh = awk "NR == 3 {print; exit}" /var/www/test/test.txt với điều này tôi đọc dòng 3 từ tệp văn bản có tên test.txt. Khi tôi nhận được một chuỗi, tôi muốn sử dụng chuỗi này làm đầu vào để tạo thư mục
user208413

1
Thay đổi điều đó thành vh=$(awk "NR==3 {print;exit}" /var/www/test.txt). Sau đó, bạn sẽ có chuỗi được lưu trong biến $vh, vì vậy bạn có thể sử dụng chuỗi như vậy: mkdir "/var/www/$vh"- điều này sẽ tạo một thư mục có tên được chỉ định bên trong / var / www.
Tomas Aschan

Tôi đã làm theo cách này nhưng nó vẫn không thể tạo thư mục :(
user208413

@ user208413: Bạn nhận được thông báo lỗi nào? "Thật không hiệu quả", thật không may, không phải là một mô tả vấn đề rất hữu ích ...
Tomas Aschan


3
name=$(<"$file") 

Từ man bash:1785, thay thế lệnh này tương đương name=$(cat "$file")nhưng nhanh hơn.



0

Nếu bạn muốn sử dụng nhiều chuỗi, bạn có thể đi với:

path="/foo/bar";
for p in `cat "$path"`;
do echo "$p" ....... (here you would pipe it where you need it) 

HOẶC LÀ

Nếu bạn muốn người dùng chỉ ra tập tin

read -e "Specify path to variable(s): " path;
for p in 'cat "$path"';
do echo "$p" ............................

0
#! /bin/bash
#  (GPL3+) Alberto Salvia Novella (es20490446e)


variableInFile () {
    variable=${1}
    file=${2}

    source ${file}
    eval value=\$\{${variable}\}
    echo ${value}
}


variableInFile ${@}

0

Tôi sử dụng điều này để có được một biến duy nhất từ ​​một tập tin

GET_VAR=$(grep --color=never -Po "^${GET_VAR}=\K.*" "${FILE}" || true)

Khi GET_VARkhông tìm thấy trong ${FILE}đó sẽ để trống thay vì gây ra lỗi nhờ || true.

Nó sử dụng grep -Ptrong GNU grep nhưng không được mặc định trong tất cả các grep tại thời điểm viết này.


Điều này dường như không làm việc cho tôi. $ Ban đầu ném một lỗi cho nhân vật bất hợp pháp
ginna
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.