Прежде всего, существующие вопросы не решили мою проблему, поэтому я спрашиваю снова.
У меня есть два текстовых файла temp.txt
adam 12
george 15
thomas 20
и демо.txt
mark 8
richard 11
james 18
Я хочу объединить их и добавить третий столбец в качестве имен файлов без расширения, например:
adam 12 temp
george 15 temp
thomas 20 temp
mark 8 demo
richard 11 demo
james 18 demo
Я использовал этот скрипт:
for i in $(ls); do name=$(basename -s .txt $i)| awk '{OFS = "\t";print $0, $name} ' $i; done
Но это дает следующую таблицу:
mark 8 mark 8
richard 11 richard 11
james 18 james 18
adam 12 adam 12
george 15 george 15
thomas 20 thomas 20
Я не понимаю, почему он дает переменную имени как всю таблицу.
Заранее спасибо.
взгляните на переменную awk FILENAME
Awk не имеет доступа к переменным Bash и наоборот. Внутри скрипта Awk name
не определено, поэтому $name
интерпретируется как $0
.
Кроме того, не используйте ls в скриптах, и цитируйте свои переменные оболочки.
Наконец, присваивание name
ничего не печатает, поэтому передача его вывода в Awk не имеет смысла.
for i in ./*; do
name=$(basename -s .txt "$i")
awk -v name = "$name" '{OFS = "\t";print $0, $name}' "$i"
done
Таким образом, вычисление basename
можно легко выполнить в Awk, но я оставлю это в качестве упражнения. (Подсказка: sub(regex, "", FILENAME)
)
Во-первых, вам нужно размаскировать $name
, который находится внутри одинарных кавычек, поэтому он не заменяется именем файла из оболочки. После этого вам нужно добавить двойные кавычки вокруг $name
, чтобы awk увидел это как строку:
for i in $(ls); do name=$(basename -s .txt $i); awk '{OFS = "\t";print $0, "'$name'"} ' $i; done
Это потерпит неудачу особым образом, если имена файлов содержат кавычки, точки с запятой, пробелы и т. д.
Это содержит несколько анти-шаблонов и дополнительные неэффективности.
awk
имеет переменную FILENAME
, значением которой является путь к обрабатываемому файлу, и переменную FNR
, значением которой является номер текущей строки в файле;
поэтому в FNR == 1
вы можете обработать FILENAME
и сохранить результат в переменной, которую вы будете использовать впоследствии:
awk -v OFS='\t' '
FNR == 1 {
basename = FILENAME
sub(".*/", "", basename) # strip from the start up to the last "/"
sub(/\.[^.]*$/, "", basename) # strip from the last "." up to the end
}
{ print $0, basename }
' ./path/temp.txt ./path/demo.txt
adam 12 temp
george 15 temp
thomas 20 temp
mark 8 demo
richard 11 demo
james 18 demo
Использование BASH:
for i in temp.txt demo.txt ; do while read -r a b ; do printf "%s\t%s\t%s\n" "$a" "$b" "${i%%.*}" ; done <"$i" ; done
Выход:
adam 12 temp
george 15 temp
thomas 20 temp
mark 8 demo
richard 11 demo
james 18 demo
Для каждого исходного файла прочитайте каждую строку и используйте printf
для вывода столбцов с разделителями табуляции, включая текущее имя исходного файла без расширения с помощью расширения параметра bash.
скопируйте / вставьте свой сценарий оболочки в shellcheck.net и исправьте проблемы, о которых он вам говорит.