Как выполнить поиск значения в файле CSV, а затем получить другое значение, связанное с ним?

Apparix es otra herramienta que hace esto. Una de sus características útiles es que puede saltar directamente a los subdirectorios de la marca y la pestaña -completa en esos subdirectorios -.

2
28.06.2019, 22:42
6 ответов

Следующий awk-код делает то, что вы просите:

#!/bin/bash

filetosearch=myfile.csv
searchString=${1:-anotherLabel}

awk -F',' -v pat="$searchString" '
BEGIN{patl=tolower(pat);flag=0};
{prev=$1}(tolower($0)==patl){flag=1;exit}
END{
     if(flag){
          print prev
             }else{
          printf("%s%s%s\n", prev+1,FS,pat) >> ARGV[1]    # use ARGIND in gawk.
          print prev+1
             }
   }' "${filetosearch}"

Поиск строки "${searchString}", которая точно соответствует полной строке (изменение tolower($0)==patlна tolower($0)~patlдля более слабого соответствия )и сообщает, по какому индексу она была найдена. Если строка не соответствует, она добавляется (в конце )к используемому файлу с индексом, который на единицу больше, чем последний индекс файла.

Пример:

$./script aLabel
445

$./script anotherLabel
446

$./script MissingLabel
450

$ cat myfile.csv
445,aLabel
446,anotherLabel
447,aThirdLabel
448,dhdhdhdhdhd
449,anotherLabel4646
450,MissingLabel
1
27.01.2020, 21:55

Это то, что вам нужно:

$ awk -v tgt='the string you want to find' '
    BEGIN { FS=OFS="," }
    tolower($2) == tolower(tgt) { print $1 | "cat>&2"; f=1 }
    { print; p=$1 }
    END { if (!f) { print ++p, tgt; print p | "cat>&2"} exit !f }
' file

Например:

$ var=$( { awk -v tgt='anotherLabel' 'BEGIN{FS=OFS=","} tolower($2) == tolower(tgt){print $1 | "cat>&2"; f=1} {print; p=$1} END {if (!f) { print ++p, tgt; print p | "cat>&2"} exit !f}' file > out1; } 2>&1 )
$ echo "exit status: $?, value found: $var"
exit status: 0, value found: 446
$ cat out1
445,aLabel
446,anotherLabel
447,aThirdLabel

$ var=$( { awk -v tgt='missingLabel' 'BEGIN{FS=OFS=","} tolower($2) == tolower(tgt){print $1 | "cat>&2"; f=1} {print; p=$1} END {if (!f) { print ++p, tgt; print p | "cat>&2"} exit !f}' file > out1; } 2>&1 )
$ echo "exit status: $?, value found: $var"
exit status: 1, value found: 448
$ cat out1
445,aLabel
446,anotherLabel
447,aThirdLabel
448,missingLabel

В приведенном выше примере любой $1, совпадающий с $2 или вновь добавленный в конец файла, будет напечатан в stderr (, который затем фиксируется в переменной, «var» )устанавливает статус выхода как успех, если целевая строка была найдена, в противном случае произойдет сбой, и выведите весь файл на стандартный вывод с добавлением отсутствующего значения, если это необходимо.

1
27.01.2020, 21:55

Попробуйте:

 awk -F',' '{ if ($2 == "anotherLabel") { print $1 } }' myfile.csv
1
27.01.2020, 21:55

Использование grepиtail:

search="anotherLabel"
file=myfile.csv

if value=$(grep -Pio -m1 "^[0-9]+(?=,$search$)" "$file"); then
    echo "do something with $value"
elif lastvalue=$(tail -n1 "$file" | grep -o '^[0-9]\+'); then
    # append lastvalue + 1 and search string
    echo "$((++lastvalue)),$search" >> "$file"
else
    # handle error
    echo "error. no integer value in last line of \"$file\" found." >&2
fi

В первом grepиспользуются следующие опции:

  • -Pвключить Perl -совместимое регулярное выражение (PCRE )для использования положительного просмотра вперед (см. ниже ).
  • -iигнорировать регистр в шаблоне
  • -oвывести только совпадающую часть строки
  • -m1остановить после первого совпадения

Первое регулярное выражение ^[0-9]+(?=,$search$)использует положительный просмотр вперед (?=pattern)для сопоставления числа, за которым следует ,и строки поиска без запятой, а строка поиска является частью самого совпадения. В сочетании с опцией -oпечатается только совпадающая часть (с номером ).

1
27.01.2020, 21:55

Вы могли бы сделать это немного короче если вы сняли диагностику и обработку ошибок -:

file="myfile.csv"
label="$1"
if [ "$label" != "" ]
then
        IFS="," read val1 val2 <<< "$(awk -F, -v look4="$label" \
                'tolower($2) == tolower(look4) { found=1; print $1 "," $2; }
                        END { if (!found) print $1; }' "$file")"
        if [ "$val2" != "" ]
        then
                echo "Found value $val1 with label $val2."
        else
                val1=$((val1+1))
                if printf "%s,%s\n" "$val1" "$label" >> "$file"
                then
                        echo "Added value $val1 to file for label $label."
                else
                        echo "Failed to add value $val1 to file."
                fi
        fi
else
        echo "Missing label."
        exit
fi

Это основано на ответе Барта , используя awkдля сравнения второго поля($2)в каждой строке к желаемой метке, но делает тестовый пример -нечувствительным. После запуска приведенного выше кода $var1будет содержать значение, соответствующее $label, так или другой. Если $var2не пусто, то оно содержит найденную метку точно . Если $var2пусто, ярлык не найден (и была предпринята попытка добавить его в файл ).

0
27.01.2020, 21:55

Я сделал с приведенным ниже скриптом

Дайте мне знать, если есть какие-либо данные

count=`awk '{print NR}' o.txt| awk '{print NR}'|sed -n '$p'`

for ((i=1;i<=$count;i++)); do sed -n ''$i'p' o.txt| grep "anotherLabel">/dev/null; if [[ $? == 0 ]]; then echo "anotherlabel exists"; awk -F "," -v i="$i"  'NR==i && $2 == "anotherLabel" {print $1}' o.txt; uni_anotherlabel=`sed -n ''$i'p' o.txt| grep "anotherLabel"| awk -F "," '{print $1}'`;else echo "anotherlabel doesnt exsists"; echo "$uni_anotherlabel"; fi; done
0
27.01.2020, 21:55

Теги

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