Игнорируя задачу XY и отвечая на вопрос в теме, можно было сделать:
#! /usr/bin/perl
":" || q@<<"=END_OF_PERL"@;
# perl code here
exec "bash", "--", $0, @ARGV;
=END_OF_PERL@
# bash code here
bash
будет игнорировать часть до строки =END_OF_PERL@
, потому что это:
: || something <<"=END_OF_PERL@"
...
=END_OF_PERL@
, в то время как первая строка в perl состоит всего из двух строк(":"
и q@quoted-string@
), объединенных по ИЛИ, поэтому -op.
=END_OF_PERL@
в perl
является началом разделаpod
(документации ), который игнорируется perl
.
Обратите внимание, что если вы хотите передать переменные из perl
в bash
, вы должны экспортировать их в среду (, хотя вы также можете использовать аргументы; здесь мы пересылаем список аргументов, полученных скриптом perl
, скрипту bash
):
$ENV{ENV_VAR} = $perl_var;
Код предполагает, что часть perl
не изменяет текущий рабочий каталог, иначе, если бы $0
был относительным путем, он стал бы недействительным при передаче в bash
. Чтобы обойти это, вы можете указать абсолютный путь к скрипту в начале с помощью:
#! /usr/bin/perl
":" || q@<<"=END_OF_PERL"@;
use Cwd "fast_abs_path";
my $script_path = fast_abs_path $0;
# perl code here
exec "bash", "--", $script_path, @ARGV;
=END_OF_PERL@
# bash code here
Это один из примеров многоязычного сценария, который является допустимым кодом более чем на одном языке. Если вам нравятся эти трюки, вы можете взглянуть на , более экстремальный здесь или codegolf Q&A .
perldoc perlrun
показывает еще один пример полиглота sh
+ perl
, но на этот раз sh
вызывается первым (для систем, которые не поддерживают -удары ).
Посмотрите, работает ли этот сценарий оболочки для вас:
#!/bin/bash
if [ $# -eq 0 ]; then
echo "You have to specify a file. Exiting..."
exit 1
fi
if [ ! -r $1 ]; then
echo "File '$1' doesn't exist or is not readable. Exiting..."
exit
fi
# count every line
lines=$(wc -l $1 | awk '{print $1}')
echo "$lines total lines."
# count '//' comments
commentType1=$(sed -ne '/^[[:space:]]*\/\//p' $1 | wc -l | awk '{print $1}')
echo "$commentType1 lines contain '//' comments."
# count single line block comments
commentType2=$(sed -ne '/^[[:space:]]*\/\*.*\*\/[[:space:]]*/p' $1 | wc -l)
echo "$commentType2 single line block comments"
# write code into temporary file because we need to tamper with the code
tmpFile=/tmp/$(date +%s%N)
cp $1 $tmpFile
# remove single line block comments
sed -ie '/^[[:space:]]*\/\*.*\*\/[[:space:]]*/d' $tmpFile
# count multiline block comments
commentType3=$(sed -ne ':start /^[[:space:]]*\/\*/!{n;bstart};p; :a n;/\*\//!{p;ba}; p' $tmpFile | wc -l | awk '{print $1}')
echo "$commentType3 of lines belong to block comments."
percent=$(echo "scale=2;($commentType1 + $commentType2 + $commentType3) / $lines * 100" | bc -l)
echo "$percent% of lines are comments"