Если вы используете международную клавиатуру США(us _intl ), вы можете сделать Alt Gr + Shift + ;
Основная проблема заключается в этой строке newval=ref[val]
, где переменная val
в качестве ключа (равна $1
в val=$1
), что на самом деле означает newval=ref[$1]
, с этой строкой newval
содержимому переменной присваивается значение ref[val]
из массива ref[], если этот ключ существовал, иначе присваивается пустое значение; делая это таким образом, т.е. newval=ref[val]
если ключ не был найден в массиве, этот ключ будет добавлен в массив с пустым значением, с которым вы можете столкнуться с некоторыми проблемами в будущем, когда вы не хотите, чтобы размер/индексы вашего массива изменялись или он может превысить доступную память или значительно замедлить работу сценария, если этот файл огромен.
... тогда в операторе if -else, и вы тестируете newval
, всегда выполняется часть else
.
if (newval in ref) {
outval = val; ## this section never runs
} else {
outval = newval ## this sections runs for every tests
}
поэтому всякий раз, когда в строке newval=ref[val]
ключ существует, outval
будет принимать значение этого ключа, иначе для него будет установлено пустое значение. и, напечатав в print outval
, это выведет значение этих ключей, если они были найдены в массиве ref[], или пустую строку в противном случае.
простое исправление (без дополнительных улучшений ), заменит эту строку на эту:
newval = (val in ref)?ref[val]:val
Ваша команда all может быть записана следующим образом:
$ awk 'BEGIN{ FS="," }
NR==FNR { ref[$1]=$2; next }
($1 in ref){ $1=ref[$1] }1' reference infile
100007
101
120
130
100007
$ cat reference
100,100007
$ cat infile
100
101
120
130
100
Дано
reffile="mycodes"
while(getline<reffile>0) {ref[$1]=$2}
пустая строка в mycodes
создает элемент ref
, значением которого является пустая строка, а индексом опять же является пустая строка.
Затем, при обработке входного потока, в
newval=ref[val]
newval
присваивается пустая строка каждый раз, когда $1
(100
, 101
, 120
,130
)не является 100
, единственным индексом в ref
, элемент которого не пуст (индексами являются начальные 100
и""
(пустые ), плюс пустые элементы, впоследствии созданные каждым newval=ref[val]
, т.е. 101
, 120
,130
). В этих случаях, поскольку пустая строка является одним из индексов ref
,в
if (newval in ref) { outval=val}
else {outval=newval}
if (newval in ref)
выполняется успешно, и напечатанное значение является текущим значением из входного потока (val
, из val=$1
).
С другой стороны, если ref
не имеет элемента с пустой строкой в качестве индекса (, как это происходит, когда вmycodes
)нет пустой строки, тогда if (newval in ref)
терпит неудачу каждый раз, когда newval
является пустой строки. А затемnewval
(печатается пустая строка ).
В обоих случаях, когда $1
равно 100
, newval
присваивается значение 10007
; if (newval in ref)
терпит неудачу, поэтому newval
печатается.
Обратите внимание, что то же загадочное поведение может быть вызвано пустой строкой во входном потоке, даже если в файле mycodes
не было пустой строки.
Предполагая, что в вашем вопросе один или несколько из 10007
, 100007
и «пятизначный код» являются опечаткой, и вы на самом деле всегда имеете в виду10007
(пять цифр ), я бы переписал ваш AWK запрограммировать как:
awk -v FS=, '
NR == FNR {
ref[$1] = $2
next
}
($1 in ref) {
$1 = ref[$1]
}
1
'./mycodes -
или
awk '
BEGIN {
FS=","
while ( (getline < "mycodes") > 0 )
ref[$1] = $2
}
($1 in ref) {
$1 = ref[$1]
}
1
' -
(Спасибо αғsнιη за указание, что newval=ref[val]
фактически добавляет val
в качестве индекса к ref
и что ($1 in ref)
, следовательно, является более безопасным способом поиска в массиве соответствующего индекса ).
val=$1
newval=ref[val]
if (newval in ref) { outval=val }
else { outval=newval }
Итак, вы читаете val
из основного входного файла, и это такие значения, как 100
или 123
. С ref
, содержащим пары вроде ref[100]=100007
, вы, вероятно, захотите проверить, существует ли val
как ключ в ref
(, то есть существует ли элемент ref[val]
). И не в том случае, если ref[val]
существует как ключ (или ref[ref[val]]
как элемент ).
Так сделай это if (val in ref)
.
Затем, если он существует , вы, вероятно, захотите использовать найденное оттуда значение (то, которое у вас есть в newval
), а если не , то значение старое значение(val
). Так сделай это
val=$1
newval=ref[val]
if (val in ref) { outval=newval }
else { outval=val }
За исключением того, что, как упоминает @αғsнιη, теперь у вас есть проблема, заключающаяся в том, что присваиваниеnewval=ref[val]
создаетref[val]
с пустой строкой в качестве значения, если она еще не существует, поэтому нам нужно что-то с этим сделать.
Либо вообще удалить newval
и использовать ref[val]
только после теста:
val=$1
# newval=ref[val] # remove this line
if (val in ref) { outval=ref[val] }
else { outval=val }
Или оставьте его там и проверьте его на пустой строке:
val=$1
newval=ref[val]
if (newval != "") { outval=newval }
else { outval=val }
Разница между ними имеет смысл, если mycodes
может содержать пустые значения во втором поле.
Если вы собираетесь использовать getline
для заполнения $0
, то вот как это сделать (см.http://awk.freeshell.org/AllAboutGetline):
while ( (getline < reffile) > 0 ) {
ref[$1] = $2
}
и остальная часть вашего скрипта должна состоять из одной строки:
{ print ( $1 in ref ? ref[$1] : $1 ) }
так что весь сценарий:
BEGIN {
FS = ","
reffile = "mycodes"
while ( (getline < reffile) > 0 ) {
ref[$1] = $2
}
}
{ print ( $1 in ref ? ref[$1] : $1 ) }
Я предполагаю, что у вас есть веская причина для создания переменной для хранения имени файла "mycodes"
и вы не хотите передавать ее в качестве аргумента.
В качестве альтернативы вы можете просто сделать:
BEGIN { FS = "," }
NR==FNR { ref[$1] = $2; next }
{ print ( $1 in ref ? ref[$1] : $1 ) }
и назовите его awk 'script' mycodes file
. Это немного менее эффективно, чем заполнение refs[]
в BEGIN
циклом getline
, но это вряд ли будет проблемой для большинства приложений и, очевидно, использует более краткий и -более сложный -для -получения -неверный код.
Выполнение print ( $1 in ref ? ref[$1] : $1 )
немного более эффективно, чем выполнение if ($1 in ref) $1=ref; print $1
или подобное, потому что оно не заставляет awk перестраивать текущую запись, но, опять же, маловероятно, что оно будет значительным.
Тем не менее, несмотря на то, что у него есть проблемы, ваш существующий скрипт, вероятно, не будет давать сбоев в том виде, как вы описываете, и ваша реальная проблема заключается в окончаниях строк DOS (см.https://stackoverflow.com/questions/45772525/why-does-my-tool-output-overwrite-itself-and-how-do-i-fix-it?).