Скрипт оболочки для вставки строк между файлом

Это зависит от того, что должен содержать файл. Если он предназначен для содержания разделенного IFS списка глобусов оболочки, например (при условии, что значение по умолчанию $IFS):

/var/log/*.log /var/adm/*~
/some/dir/*.txt

Тогда для i в $(cat file)будет путь. Именно это и делает этот $(cat file)без кавычек: примените оператор split+glob к выходным данным cat file, лишенным завершающих символов новой строки. Таким образом, он будет перебирать каждое имя файла, полученное в результате расширения этих глобусов (за исключением случаев, когда глобусы не соответствуют ни одному файлу, где это оставило бы глобус там, но нерасширенным).

Если вы хотите перебрать каждую строку с разделителями file, вы должны сделать:

while IFS= read -r line <&3; do
{
  something with "$line"
} 3<&-
done 3< file

С помощью цикла forвы можете перебрать каждую непустую строку с помощью :

IFS='
' # split on newline only (actually sequences of newlines and
  # ignoring leading and trailing ones as newline is a
  # IFS whitespace character)
set -o noglob # disable the glob part of the split+glob operator:
for line in $(cat file); do
   something with "$line"
done

Однако a:

while read line; do
  something with "$line"
done < file

Имеет мало смысла. Это чтение содержимого файлаочень запутанным способом, где символы $IFSи обратные косые черты обрабатываются особым образом.

В любом случае, ARG_MAX ограничивает текст, на который вы цитируете, относится к системному вызову execve()(на совокупный размер аргументов и переменных среды), поэтому применяется только к случаям где команда в файловой системе выполняется с, возможно, очень длинным расширением оператора split+glob, примененного к подстановке команды (этот текст вводит в заблуждение и неверен в нескольких учетных записях).

Это применимо, например, в:

cat -- $(cat file) # with shell implementations where cat is not builtin

Но не в:

for i in $(cat file)

где нет системного вызова execve().

Сравните:

bash-4.4$ echo '/*/*/*/*' > file
bash-4.4$ true $(cat file)
bash-4.4$ n=0; for f in $(cat file); do ((n++)); done; echo "$n"
523696
bash-4.4$ /bin/true $(cat file)
bash: /bin/true: Argument list too long

Это нормально со встроенной командой bash's trueили с циклом for, но не при выполнении /bin/ правда. Обратите внимание, что файлимеет размер всего 9 байт, но расширение $(cat file)составляет несколько мегабайт, потому что /*/*/*/*glob расширяется оболочкой.

Дополнительная литература:

0
25.05.2016, 16:12
2 ответа

Я бы сделал это:

names=$(sed s/^/Name=/ file1.txt)

ed file2.txt <<END
/^end$/i
$names
.
wq
END

сейчас:

$ cat file2.txt
<project>
<target>
start
Name=Ramesh
Name=Suresh
Name=Raman
end
</target>
</project>
2
28.01.2020, 02:27

Вы можете использовать awk

awk 'NR==FNR{Lines=Lines "Name=" $0 "\n";next}/end/{print Lines $0 ;next}1' file{1,2}

<project>
<target>
start
Name=Ramesh
Name=Suresh
Name=Raman
end
</target>
</project>
1
28.01.2020, 02:27

Теги

Похожие вопросы