逐行读取文件,将值赋给变量

时间:2012-06-07 09:49:10

标签: bash

我有以下.txt文件:

 
Marco
Paolo
Antonio

我想逐行阅读,对于每一行,我想将.txt行值分配给变量。假设我的变量为$name,则流程为:

  • 从文件中读取第一行
  • 分配$name =“Marco”
  • 使用$name
  • 执行某些任务
  • 从文件中读取第二行
  • 分配$name =“Paolo”

10 个答案:

答案 0 :(得分:1195)

以下内容读取逐行作为参数传递的文件:

#!/bin/bash
while IFS= read -r line; do
    echo "Text read from file: $line"
done < "$1"

这是用于从循环中的文件读取行的standard form。说明:

  • IFS=(或IFS='')可防止修剪前导/尾随空格。
  • -r可防止解释反斜杠转义。

如果上述内容保存到文件名为readfile的脚本中,则可以按如下方式运行:

chmod +x readfile
./readfile filename.txt

如果文件不是standard POSIX text file(=未被换行符终止),则可以修改循环以处理尾随的部分行:

while IFS= read -r line || [[ -n "$line" ]]; do
    echo "Text read from file: $line"
done < "$1"

此处,|| [[ -n $line ]]会阻止最后一行被忽略,如果它不以\n结尾(因为read在遇到EOF时返回非零退出代码)。

如果循环内的命令也从标准输入读取,read使用的文件描述符可能会被其他东西(避免standard file descriptors),例如:

while IFS= read -r -u3 line; do
    echo "Text read from file: $line"
done 3< "$1"

(非Bash shell可能不知道read -u3;请改用read <&3。)

答案 1 :(得分:288)

我建议您使用代表-r的{​​{1}}标记:

read

我引用-r Do not treat a backslash character in any special way. Consider each backslash to be part of the input line.

另一件事是将文件名作为参数。

这是更新的代码:

man 1 read

答案 2 :(得分:125)

使用以下Bash模板应该允许您从文件中一次读取一个值并进行处理。

while read name; do
    # Do what you want to $name
done < filename

答案 3 :(得分:66)

import java.awt.Dimension;
import java.awt.EventQueue;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;

/**
 * @see https://stackoverflow.com/a/34742409/230513
 * @see https://stackoverflow.com/a/24762078/230513
 */
public class WorkerTest {

    private static final int N = 1_000;
    private static final String URL = "jdbc:h2:mem:test";
    private static final Random r = new Random();

    private void display() {
        JFrame f = new JFrame("WorkerTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        createTestDatabase(N);
        JDBCModel model = new JDBCModel(getConnection(), "select * from city");
        f.add(new JScrollPane(new JTable(model) {

            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(320, 240);
            }
        }));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class Row {
        int ID;
        String name;
    }

    private static class JDBCModel extends AbstractTableModel {

        private final List<Row> data = new ArrayList<>();
        private ResultSet rs = null;
        private ResultSetMetaData meta;

        public JDBCModel(Connection conn, String query) {
            try {
                Statement s = conn.createStatement();
                rs = s.executeQuery(query);
                meta = rs.getMetaData();
                JDBCWorker worker = new JDBCWorker();
                worker.execute();
            } catch (SQLException e) {
                e.printStackTrace(System.err);
            }
        }

        @Override
        public int getRowCount() {
            return data.size();
        }

        @Override
        public int getColumnCount() {
            try {
                return meta.getColumnCount();
            } catch (SQLException e) {
                e.printStackTrace(System.err);
            }
            return 0;
        }

        @Override
        public Object getValueAt(int rowIndex, int colIndex) {
            Row row = data.get(rowIndex);
            switch (colIndex) {
                case 0:
                    return row.ID;
                case 1:
                    return row.name;
            }
            return null;
        }

        @Override
        public String getColumnName(int colIndex) {
            try {
                return meta.getColumnName(colIndex + 1);
            } catch (SQLException e) {
                e.printStackTrace(System.err);
            }
            return null;
        }

        private class JDBCWorker extends SwingWorker<List<Row>, Row> {

            @Override
            protected List<Row> doInBackground() {
                try {
                    while (rs.next()) {
                        Row r = new Row();
                        r.ID = rs.getInt(1);
                        r.name = rs.getString(2);
                        publish(r);
                    }
                } catch (SQLException e) {
                    e.printStackTrace(System.err);
                }
                return data;
            }

            @Override
            protected void process(List<Row> chunks) {
                int n = getRowCount();
                for (Row row : chunks) {
                    data.add(row);
                }
                fireTableRowsInserted(n, n + chunks.size());
            }
        }
    }

    private static void createTestDatabase(int n) {
        Connection conn = getConnection();
        try {
            Statement st = conn.createStatement();
            st.execute("create table city(id integer, name varchar2)");
            PreparedStatement ps = conn.prepareStatement(
                "insert into city values (?, ?)");
            for (int i = 0; i < n; i++) {
                ps.setInt(1, i);
                ps.setString(2, (char) ('A' + r.nextInt(26))
                    + String.valueOf(r.nextInt(1_000_000)));
                ps.execute();
            }
        } catch (SQLException ex) {
            ex.printStackTrace(System.err);
        }
    }

    private static Connection getConnection() {
        try {
            return DriverManager.getConnection(URL, "", "");
        } catch (SQLException e) {
            e.printStackTrace(System.err);
        }
        return null;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new WorkerTest()::display);
    }
}

答案 4 :(得分:20)

许多人发布了一个过度优化的解决方案。我不认为这是不正确的,但我谦卑地认为,一个不太优化的解决方案将是可取的,让每个人都能轻松理解这是如何工作的。这是我的建议:

#!/bin/bash
#
# This program reads lines from a file.
#

end_of_file=0
while [[ $end_of_file == 0 ]]; do
  read -r line
  # the last exit status is the 
  # flag of the end of file
  end_of_file=$?
  echo $line
done < "$1"

答案 5 :(得分:17)

使用:

filename=$1
IFS=$'\n'
for next in `cat $filename`; do
    echo "$next read from $filename" 
done
exit 0

如果您以不同方式设置IFS,则会得到奇怪的结果。

答案 6 :(得分:9)

如果您需要处理输入文件和用户输入(或stdin中的任何其他内容),请使用以下解决方案:

#!/bin/bash
exec 3<"$1"
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
    read -p "> $line (Press Enter to continue)"
done

基于the accepted answerbash-hackers redirection tutorial

这里,我们打开作为脚本参数传递的文件的文件描述符3,并告诉read使用此描述符作为输入(-u 3)。因此,我们将默认输入描述符(0)附加到终端或另一个输入源,能够读取用户输入。

答案 7 :(得分:7)

正确处理错误:

#!/bin/bash

set -Ee    
trap "echo error" EXIT    
test -e ${FILENAME} || exit
while read -r line
do
    echo ${line}
done < ${FILENAME}

答案 8 :(得分:0)

以下内容只会打印出文件内容:

cat $Path/FileName.txt

while read line;
do
echo $line     
done

答案 9 :(得分:0)

在bash中使用IFS(内部字段分隔符)工具,定义用于将行分隔为标记的字符,默认情况下包括<< strong> tab > / << strong> space > / < newLine >

步骤1 :加载文件数据并插入列表:

# declaring array list and index iterator
declare -a array=()
i=0

# reading file in row mode, insert each line into array
while IFS= read -r line; do
    array[i]=$line
    let "i++"
    # reading from file path
done < "<yourFullFilePath>"

第2步:现在迭代并打印输出:

for line in "${array[@]}"
  do
    echo "$line"
  done

在数组中回显特定的索引:访问数组中的变量:

echo "${array[0]}"