В сценарии отсутствует awk
:
awk 'BEGIN{FS=OFS="|"} NR==FNR{$1="";++a[$0];next} {field1=$1;$1=""; if ( !(a[$0]) ) {$1=field1;print $0} }' \
/home/path/a.txt /home/path/b.txt > /home/path/c.txt
Вероятно, в первой строке сценария также должно быть #!/bin/sh
.
В качестве альтернативы вы можете преобразовать скрипт в правильный awk
скрипт:
#!/usr/bin/awk -f
BEGIN {FS = OFS = "|"}
NR==FNR { $1="";++a[$0]; next }
{
field1 = $1;
$1 = "";
if ( !(a[$0]) ) {
$1 = field1;
print $0;
}
}
... и затем запустить его, например, с помощью
$ ./bb.awk /home/path/a.txt /home/path/b.txt >/home/path/c.txt
Сам по себе немного слишком сложный, но с соблюдением формата, предоставленного большинством других, но без вызова IFS, который я бы использовал.
pairs=( "name1,url1" "name2,url2" "name3,url3" )
for pair in "${pairs[@]}"; do
#Create an array in itself, of the two values.
tmpArr=(`echo $pair | tr ',' ' '`)
#Then either use Array Indexing on the array ie.
#Or place the offsets in their own variables. ie Run=${tmpArr[0] ...;
command ${tmpArr[0]} ${tmpArr[1]}
done
Устраняет необходимость во временных файлах, никакой реальной очистки не требуется, если они используются внутри сценарий, который изначально использует Sha-Bang или делает его локальным в функции, как я и делал большую часть своих сценариев, сохраняя синтаксис как можно ближе к "C". Я также придерживаюсь моего девиза bash: «Если вы хотите это сделать, значит, кто-то уже делал это раньше и сделал модуль, так что не выполняйте эту работу заново ...»
Вначале я обратил внимание на такую сложную вещь, как ассоциативные массивы.
Затем я понял, что это можно сделать так же просто, как показано ниже, учитывая, что у вас столько же имен, сколько URL:
root@debian:a=( "name1,url1" "name2,url2" "name3,url3" );while IFS="," \
read -r name url;do echo "command $name $url";done<<<$(printf '%s\n' "${a[@]}")
command name1 url1
command name2 url2
command name3 url3
Все, что вам нужно, это хранить имена и URL-адреса в одном массиве (в моем test) вместе, через запятую.
Возможно, вам подойдет простой сценарий bash:
pairs=( "name1,url1" "name2,url2" "name3,url3" )
for pair in "${pairs[@]}"; do
IFS=, read name url <<<"${pair}"
printf "%s %s\n" "${name}" "${url}"
command "${name}" "${url}"
done
bash
довольно ограничен на этом фронте. Вы можете попробовать другие оболочки.
С zsh
(вы уже используете синтаксис zsh
, поскольку вы не указали свои переменные в команде $ NAME $ URL
):
for name url (
name1 url1
name2 url2
name3 url3
) command $name $url
С bash
или другой оболочкой POSIX вы можете сделать:
while IFS=, read <&3 -r name url; do
{
command "$name" "$url"
} 3<&-
done 3<< "EOF"
name1,url1
name2,url2
name3,url3
EOF
Это означает, что значения не могут содержать запятые или символы новой строки.
Последние версии bash
также поддерживают ассоциативные массивы, используя синтаксис, больше похожий на синтаксис ksh93, чем на zsh
. Итак, если имена уникальны, вы можете сделать:
typeset -A pairs
pairs=(
[name1]=url1
[name2]=url2
[name3]=url3
)
for name in "${!pairs[@]}"; do
url=${pairs[$name]}
command "$name" "$url"
done
Это также будет работать в ksh93
. Помните, что правила цитирования между ними немного различаются. В zsh
синтаксис определения ассоциативного массива более простой, и применяются обычные правила цитирования:
pairs=(name1 url1 name2 url2 name3 url3)
Которые вы можете поместить в несколько строк:
pairs=(
name1 url1
name2 url2
name3 url3
)
Остерегайтесь, однако, порядок не сохраняется и что Ассоциативные массивы bash
не поддерживают пустой ключ.
ksh93
поддерживает многомерные массивы, поэтому вы можете:
pairs=((name1 url1) (name2 url2) (name3 url3))
for ((i = 0; i < ${#pairs[@]}; i++)); do
name=${pairs[i][o]} url=${pairs[i][1]}
command "$name" "$url"
done
Вы можете создать здесь-документ, который записывается во временный файл и затем обрабатывается. Временный файл будет автоматически удален, поэтому ручная очистка не требуется.
#!/bin/bash
mylist=/var/tmp/$$
trap 'rm -f ${mylist}' EXIT
cat << _EOF_ > ${mylist}
name1 url1
name2 url2
name3,url3
_EOF_
while read name url
do
printf "%s %s\n" ${name} ${url}
done < ${mylist}