Я хотел бы знать, есть ли какой-либо способ чтения из двух входных файлов во вложенном цикле while по одной строке за раз. Например, допустим, у меня есть два файла FileA
и FileB
.
FiLea:
[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3
FILEB:
[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3
Текущий образец скрипта:
[jaypal:~/Temp] cat read.sh
#!/bin/bash
while read lineA
do echo $lineA
while read lineB
do echo $lineB
done < fileb
done < filea
Исполнение:
[jaypal:~/Temp] ./read.sh
this is File A line1
this is File B line1
this is File B line2
this is File B line3
this is File A line2
this is File B line1
this is File B line2
this is File B line3
this is File A line3
this is File B line1
this is File B line2
this is File B line3
Проблема и желаемый результат:
Это полностью переходит на FileB для каждой строки в FileA. Я попытался использовать продолжение, разрыв, выход, но ни один из них не предназначен для достижения результата, который я ищу. Я хотел бы, чтобы скрипт считывал только одну строку из файла A, а затем одну строку из FileB, выходил из цикла и продолжал со второй строки файла A и второй строки файла B. Что-то похожее на следующий скрипт -
[jaypal:~/Temp] cat read1.sh
#!/bin/bash
count=1
while read lineA
do echo $lineA
lineB=`sed -n "$count"p fileb`
echo $lineB
count=`expr $count + 1`
done < filea
[jaypal:~/Temp] ./read1.sh
this is File A line1
this is File B line1
this is File A line2
this is File B line2
this is File A line3
this is File B line3
Этого можно добиться с помощью цикла while?
bash
shell-script
io-redirection
Джайпал Сингх
источник
источник
paste -d '\n' file1 file2
Ответы:
Если вы точно знаете, что какой-то символ никогда не появится в первом файле, тогда вы можете использовать вставку.
Пример вставки с использованием вкладки разделителя по умолчанию:
Пример использования пасты
@
:Обратите внимание, что достаточно, если символ гарантированно не встречается в первом файле. Это потому что
read
будет игнорироватьIFS
при заполнении последней переменной. Таким образом, даже если он@
встречается во втором файле, он не будет разделен.Пример вставки с использованием некоторых функций bash для возможно более чистого кода:
Используемые функции Bash: ansi c string (
$'\t'
) и process substitution (<(...)
), чтобы избежать цикла while в проблеме подоболочки .Если вы не можете быть уверены, что какой-либо символ никогда не появится в обоих файлах, вы можете использовать файловые дескрипторы .
Много не проверял. Может сломаться на пустых строках.
Файловые дескрипторы с номерами 0, 1 и 2 уже используются для stdin, stdout и stderr соответственно. Файловые дескрипторы от 3 и выше (обычно) бесплатны. Руководство по bash предупреждает об использовании файловых дескрипторов больше 9, потому что они «используются внутри».
Обратите внимание, что дескрипторы открытых файлов наследуются функциями оболочки и внешними программами. Функции и программы, наследующие дескриптор открытого файла, могут считывать (и записывать) дескриптор файла. Вы должны позаботиться о том, чтобы закрыть все файловые дескрипторы, которые не требуются, перед вызовом функции или внешней программы.
Здесь та же самая программа, что и выше, с реальной работой (печатью), отделенной от мета-работы (чтение строки за строкой из двух файлов параллельно).
Теперь мы притворяемся, что не имеем никакого контроля над рабочим кодом, и этот код по какой-либо причине пытается прочитать из файлового дескриптора 3.
Вот пример вывода. Обратите внимание, что вторая строка из первого файла «украдена» из цикла.
Вот как вы должны закрыть файловые дескрипторы перед вызовом внешнего кода (или любого другого кода).
источник
Откройте два файла в разных файловых дескрипторах . Перенаправьте ввод
read
встроенного кода в дескриптор, к которому подключен нужный файл. В bash / ksh / zsh вы можете написатьread -u 3
вместоread <&3
.Этот фрагмент останавливается, когда самый короткий файл был обработан. См. Раздел « Чтение двух файлов в цикле IFS» - есть ли способ получить результат с нулевым различием в этом случае? если вы хотите продолжить обработку до конца обоих файлов.
Смотрите также Когда бы вы использовали дополнительный файловый дескриптор? для получения дополнительной информации о файловых дескрипторах и Почему `в то время как IFS = read` используется так часто, вместо` IFS =; пока читаешь? для объяснения
IFS= read -r
.источник
Я знаю, что вы хотите сценарий оболочки, но вы можете взглянуть на
paste
команду.источник
paste
тоже крутоПопробуйте команду ниже:
источник
В качестве альтернативы, я полагаю, вы можете записать файл в переменную массива, связав каждую строку файла в массив [line_of_file_index], используя команду bash mapfile Тем не менее, я не уверен, что это только для Bash3 выше или Bash4.
http://wiki.bash-hackers.org/commands/builtin/mapfile
источник