Я хочу распечатать строки таблицы в файле, проблема в том, что когда я использую readline
, я перепечатываю результат несколько раз, вот мой входной файл
aa ,DEC ,file1.txt
aa ,CHAR ,file1.txt
cc ,CHAR ,file1.txt
dd ,DEC ,file2.txt
bb ,DEC ,file3.txt
bb ,CHAR ,file3.txt
cc ,DEC ,file1.txt
Вот результат, который я хочу получить:
напечатано в файле1.txt
aa#DEC,CHAR
cc#CHAR,DEC
напечатано в файле2.txt
dd#DEC
напечатано в файле3.txt
bb#DEC,CHAR
вот моя попытка:
(cat input.txt|while read line
do
table=`echo $line|cut -d"," -f1
variable=`echo $line|cut -d"," -f2
file=`echo $line|cut -d"," -f3
echo ${table}#${variable},
done ) > ${file}
@0stone0 сделано ; Спасибо
Вам нужно перенаправить эхо на соответствующий файл в цикле. На данный момент весь вывод идет в один файл.
Пожалуйста, скопируйте/вставьте свой скрипт на shellcheck.net (как указано в информации о теге bash, stackoverflow.com/tags/bash/info ), исправьте проблемы, о которых он говорит вам, прочитайте почему-это -используя цикл оболочки для обработки текста, считается плохой практикой, а затем опубликуйте повторно, если у вас все еще есть вопрос.
С вашими показанными образцами, не могли бы вы попробовать следовать, написать и протестировать показанные образцы в GNU awk
.
awk '
{
sub(/^,/,"",$3)
}
FNR==NR{
sub(/^,/,"",$2)
arr[$1,$3]=(arr[$1,$3]?arr[$1,$3]",":"")$2
next
}
(($1,$3) in arr){
close(outputFile)
outputFile=$3
print $1"#"arr[$1,$3] >> (outputFile)
delete arr[$1,$3]
}
' Input_file Input_file
Объяснение: Добавлено подробное объяснение вышеизложенного.
awk ' ##Starting awk program from here.
{
sub(/^,/,"",$3) ##Substituting starting comma in 3rd field with NULL.
}
FNR==NR{ ##Checking condition FNR==NR will be true when first time Input_file is being read.
sub(/^,/,"",$2) ##Substituting starting comma with NULL in 2nd field.
arr[$1,$3]=(arr[$1,$3]?arr[$1,$3]",":"")$2
##Creating arr with index of 1st and 3rd fields, which has 2nd field as value.
next ##next will skip all further statements from here.
}
(($1,$3) in arr){ ##Checking condition if 1st and 3rd fields are in arr then do following.
close(outputFile) ##Closing output file, to avoid "too many opened files" error.
outputFile=$3 ##Setting outputFile with value of 3rd field.
print $1"#"arr[$1,$3] >> (outputFile)
##printing 1st field # arr value and output it to outputFile here.
delete arr[$1,$3] ##Deleting array element with index of 1st and 3rd field here.
}
' Input_file Input_file ##Mentioning Input_file 2 times here.
это действительно работает, но не могли бы вы дать больше пояснений о строке 7 в вашем коде? что означает "?" и ,",":"")$2 в строке 14, а также в строке 14, спасибо
@BADS, добро пожаловать, рад, что вам помогло. он использует тернарные операторы. его синтаксис выглядит так: condition_check?value(when condition is TRUE):value(when condition is false)
формат. arr[$1,$3]
означает проверить, НЕ является ли оно NULL, а затем добавить значение второго поля текущей строки к его существующему значению (согласно требованию) ИЛИ добавить его заново в массив, поскольку массив будет пустым. Надеюсь, теперь все ясно, ура.
У вас есть несколько ошибок в вашем коде. Вы можете использовать встроенный read
для разделения запятой, а круглые скобки совершенно не нужны.
while IFS=, read -r table variable file
do
echo "${table}#${variable}," >>"$file"
done< input.txt
Использование $file
в редиректе после done
является ошибкой; оболочка хочет открыть дескриптор файла для перенаправления до того, как будет определено file
. Но в соответствии с вашими требованиями каждая строка должна идти в другой файл `.
Обратите также внимание на исправления цитирования и упущение бесполезного кота.
Оборачивать поля с одинаковым значением в одну и ту же строку было бы удобно с помощью постпроцессора Awk, но тогда вы могли бы также сделать все это в Awk, как и в другом ответе, который вы уже получили.
Это можно сделать за один проход gnu awk
вот так:
awk -F ' *, *' '{
map[$3][$1] = (map[$3][$1] == "" ? "" : map[$3][$1] ",") $2
}
END {
for (f in map)
for (d in map[f])
print d "#" map[f][d] > f
}' file
Это заполнит эти данные:
=== file1.txt ===
aa#DEC,CHAR
cc#CHAR,DEC
=== file2.txt ===
dd#DEC
=== file3.txt ===
bb#DEC,CHAR
Пожалуйста, покажите нам свою попытку.