
Мне нужна помощь в решении этой проблемы, у меня есть файл, содержащий список имен:
имена.txt
roger
peter
henry
Я хотел бы объединить :
после каждого имени
for i in $(cat names.txt); do
$i+=$i":"
done
Результат, который я хочу получить, это:roger:peter:henry
но я получаю этот выводroger:peter:henry:
решение1
Есть инструмент, который может сделать это за вас:paste
$ paste -sd: names.txt
roger:peter:henry
решение2
Альтернативное решение с sed
и tr
:
sed '$!s/$/:/' names.txt | tr -d '\n'
Выходы:
roger:peter:henry
решение3
paste
правильный инструмент для работы. Но просто для полноты картины, вот как сделать то, что вы пытались:
k="$(head -n1 names.txt)";
for i in $(tail -n+2 names.txt); do
k="$k:$i";
done
Это производит:
$ echo "$k"
roger:peter:henry
решение4
$i+=$i":"
Это не делает то, что вы хотите. Вместо этого оно расширяется $i
в отмеченных местах и пытается запустить результат как команду. Назначение оболочки не принимает знак доллара с левой стороны (думайте об этом как о принятии значения переменной, здесь нам это не нужно, а место для сохранения). i+=$i":"
Вместо этого должно быть так. Или, что предпочтительнее, i+="$i:"
просто привыкнуть заключать в кавычки расширения переменных оболочки.
Кроме того, вы пытаетесь добавить к переменной, используемой как переменная цикла. Это не очень полезно, так как она перезаписывается на следующем этапе цикла. Кроме того, вы добавляете двоеточие после каждого элемента, включая последний, так что у вас будет одно в конце. Но мы можем удалить его позже с помощью расширения ${var%suffix}
.
Так:
s=
for i in $(cat names.txt); do
s+="$i:"
done
s=${s%:}
Однако следует помнить, что расширение без кавычек $(cat)
будет обрабатывать любые шаблоны подстановочных знаков в именах файлов (globs), поэтому строка *
в файле будет расширена на все файлы в текущем каталоге и т. д.