У меня есть два текстовых файла (сказать text1.txt
и text 2.txt
) оба с тем же количеством строк.напр. text1.txt
содержит 4 записи
0127H
0132H
0982H
1772H
text2.txt
содержит 4 записи
stev
mary
beautiful
ugly
Теперь моя задача состоит в том, чтобы создать 4 текстовых файла как
0127H.txt
содержать stev
0132H.txt
содержать mary
0982H.txt
содержать beautiful
1772H.txt
содержать ugly
Т.е. 1-я строка text1.txt
должно быть имя файла, и соответствующая запись будет 1-й строкой text2.txt
.
Я любезно запрашиваю Вас помочь мне избавиться от поднятого вопроса.
Следующая острота сделает то, в чем Вы нуждаетесь:
bash -c "$(paste text1.txt text2.txt | awk '{print "echo "$2">"$1".txt"}')"
Это работало на меня:
c=1; while read f; do sed -n "${c}p" text2.txt >"$f.txt"; ((c++)); done <text1.txt
Это выполняет итерации канавки каждая строка в файле text1.txt
. Тогда для каждой строки sed
извлечения соответствующая строка в файле text2.txt
и записях это к, что файл с .txt
добавленный.
Я могу сделать это со следующим сценарием удара:
#!/bin/bash
FILENAME="$1"
count=0
while read LINE
do
let count++
sed -n "$count"p text2 > "$LINE".txt
done < "$FILENAME"
С awk
, можно сделать:
awk 'FNR == NR {filename[FNR] = $0 ".txt"} FNR != NR {print > filename[FNR]}' file1 file2
FNR == NR
тесты, читаем ли мы первый файл. Если это так, мы сохраняем строку в массиве.Другая опция Python:
#!/usr/bin/env python3
import sys
lines = lambda f: open(f).read().splitlines()
content = lines(sys.argv[2])
for i, item in enumerate(lines(sys.argv[1])):
open(item+".txt", "wt").write(content[i])
Это создаст обозначенные файлы в каталоге, откуда Вы запускаете скрипт
combine.py
выполните его с командой:
python3 /path/to/combine.py <file1> <file2>
Как предложено @queueoverflow, с помощью zip
опция (очень аккуратный, еще короче):
#!/usr/bin/env python3
import sys
lines = lambda f: open(f).read().splitlines()
for item, content in zip(lines(sys.argv[1]), lines(sys.argv[2])):
open(item+".txt", "wt").write(content)
Только для забавы; включая sys.argv[n]
в функции лямбды, уменьшая его немного далее:
#!/usr/bin/env python3
import sys
lines = lambda n: open(sys.argv[n]).read().splitlines()
[open(f+".txt", "wt").write(c) for f, c in list(zip(lines(1), lines(2)))]
Вот моя попытка этой задачи:
Шаг 1 - создает список всех текстовых файлов, Вы хотите иметь одно слово. Названный моим list
, и один perline перечислил text1, text2, text3, и text4
Шаг 2 - Создает список слов, один на строку. Мой называют word
Шаг 3 - выполняет следующую команду: pr -m -t words list | awk '{x=$2; print $1>x}'
Теперь, конечно, это не острота, но работало на меня. Мой список слов был one two three four
, и теперь text1 имеет one
, text2 имеет two
, и т.д
Править:
Вот моя сырая попытка адресуемых пространств между словами в файле слов: перевести \n
к другому символу и затем использованию, что символ как разделитель в awk. Я протестировал это с df | tr '\n' '@' | awk -F '@' '{for (i=1;i<5;i++) print $i > "file"i".txt" }'
Результат состоит в том, что я получил 4 различных файла с 4 последовательными строками от df
команда. Замена df
с cat words
. Вот результат
И да, этот метод не прекрасен; что, если строка содержит @
посреди него или в конце. Но этот метод гибок - @
может быть заменен с чем-то еще. Кроме того, пользователь должен, вероятно, знать при попытке в файлы текста процесса, как они разграничены; хороший пример /etc/passwd
, где поля разделяются :
, и никто вслепую не ворвался обработка того файла, правильно?
Можно выполнить в этом bash
:
IFS=$'\n'
a=($(<text1.txt))
i=0
while read -r line; do
echo "${line}" > "${a[i++]}"
done < text2.txt
IFS
присвоение говорит bash
рассматривать только новую строку как ограничителя слова. Если Вы не хотите, чтобы та установка влияла на you'r, выполняющий оболочку, Вы могли бы хотеть запустить новое bash
экземпляр для все это, или сброс IFS
впоследствии к его использованию по умолчанию IFS=$' \t\n'
.
Следующая строка имеет две части. a=( 0127H 0132H 0982H 1772H )
сделал бы a
массив с четырьмя записями. Но вместо того, чтобы перечислить записи дословно, мы заменяем содержанием файла там. $(…)
обычно выполняет команду и расширяется до ее вывода, но с продвижением <
там это ведет себя почти, как будто команда была cat
, т.е. это расширяется до содержания того файла. Вывод того файла разделяется на слова accoring к IFS
, таким образом, строки, содержащие пробел, заканчиваются в элементе единого массива.
Затем мы циклично выполняемся по строкам text2.txt
, и используйте счетчик i
определить элемент соответствия text1.txt
. Мы могли также загрузиться text2.txt
как массив, и затем выполняют итерации по обоим массивам параллельно, особенно после проверки, что их длины соглашаются.
IFS=$'\n'
a=($(<text1.txt))
b=($(<text2.txt))
if [[ ${#a[@]} -ne ${#b[@]} ]]; then
echo "Length mismatch" >& 2
else
for ((i=0; i<${#a[@]}; ++i)); do
echo "${b[i]}" > "${a[i]}"
done
fi
Сохраните ниже сценария Python как files.py
или подобный. Можно найти его здесь
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright © 2015 Martin Ueding <dev@martin-ueding.de>
# Licensed under The MIT License
import argparse
def main():
options = _parse_args()
with open(options.first) as f:
lines1 = [s.strip() for s in f.readlines()]
with open(options.second) as f:
lines2 = f.readlines()
for first, second in zip(lines1, lines2):
with open(first + '.txt', 'w') as f:
f.write(second)
def _parse_args():
'''
Parses the command line arguments.
:return: Namespace with arguments.
:rtype: Namespace
'''
parser = argparse.ArgumentParser(description='')
parser.add_argument('first')
parser.add_argument('second')
options = parser.parse_args()
return options
if __name__ == '__main__':
main()
Затем можно запустить его с
python3 files.py text1.txt text2.txt
и это генерирует все файлы, которые Вы хотите.
Преимущества этого решения:
-h
или --help
также работает просто великолепно.\n\r
и \r
).with …:
).