Na przykład, biorąc pod uwagę:
USCAGoleta9311734.5021-120.1287855805
Chcę tylko wyodrębnić:
US
Na przykład, biorąc pod uwagę:
USCAGoleta9311734.5021-120.1287855805
Chcę tylko wyodrębnić:
US
Odpowiedzi:
Prawdopodobnie najbardziej wydajną metodą, jeśli używasz bashpowłoki (i wydaje się, że tak jest, na podstawie twoich komentarzy), jest użycie wariantu podłańcucha rozwijania parametrów:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Będą shortto pierwsze dwa znaki long. Jeśli longjest krótszy niż dwa znaki, shortbędzie identyczny.
Ta metoda w powłoce jest zwykle lepsza, jeśli zamierzasz to robić dużo (np. 50000 razy na raport, jak wspomniałeś), ponieważ nie ma narzutu związanego z tworzeniem procesu. Wszystkie rozwiązania korzystające z programów zewnętrznych będą cierpieć z powodu tego obciążenia.
Jeśli chcesz również zapewnić minimalną długość, możesz wyłożyć ją przed ręką za pomocą czegoś takiego:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Zapewniłoby to, że cokolwiek o długości mniejszej niż dwa znaki zostało dopełnione po prawej stronie kropkami (lub czymś innym, po prostu zmieniając znak używany podczas tworzenia tmpstr). Nie jest jasne, czy tego potrzebujesz, ale pomyślałem, że wstawię to dla kompletności.
Powiedziawszy to, istnieje wiele sposobów, aby to zrobić za pomocą programów zewnętrznych (na przykład, jeśli nie masz bashdostępnych), z których niektóre to:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
Pierwsze dwa ( cuti head) są identyczne dla ciągu jednowierszowego - w zasadzie oba zwracają po prostu pierwsze dwa znaki. Różnią się tym, cutże dadzą ci pierwsze dwa znaki w każdej linii i headdadzą ci pierwsze dwa znaki z całego wejścia
Trzecia używa funkcji awkpodłańcucha do wyodrębnienia pierwszych dwóch znaków, a czwarta używa sedgrup przechwytywania (przy użyciu ()i \1) do przechwycenia pierwszych dwóch znaków i zastąpienia nimi całego wiersza. Oba są podobne cut- dostarczają pierwsze dwa znaki z każdego wiersza na wejściu.
Nic z tego nie ma znaczenia, jeśli masz pewność, że dane wejściowe to jedna linia, wszystkie mają identyczny efekt.
printf '%s'zamiast echow przypadku istnieją dziwne znaki w ciągu: stackoverflow.com/a/40423558/895245 Dla POSIX obsesję: head -cnie POSIX, cut -ca awk substrto, sed \1nie jestem pewien.
najłatwiej jest
${string:position:length}
Gdzie to wyodrębnia $lengthpodciąg z $stringat $position.
Jest to wbudowana funkcja bash, więc awk lub sed nie są wymagane.
Musisz zdobyć kilka dobrych odpowiedzi i pójdę z Basha wbudowane siebie, ale skoro pytasz o seda awki ( prawie ) nikt inny nie zaproponował rozwiązania oparte na nich, ofiaruję Ci te:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
i
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
To awkpowinno być dość oczywiste, ale oto wyjaśnienie sedjednego:
substr($0,1,2).
Jeśli jesteś w środku bash, możesz powiedzieć:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
To może być właśnie to, czego potrzebujesz…
Po prostu grep:
echo 'abcdef' | grep -Po "^.." # ab
-Popcję, aby ją skrócić. Wszystkie wyrażenia regularne będą rozumieć ten wzorzec.
Możesz użyć printf:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Dość późno, ale oto jest
sed 's/.//3g'
Lub
awk NF=1 FPAT=..
Lub
perl -pe '$_=unpack a2'
Jeśli chcesz używać skryptów powłoki i nie polegać na rozszerzeniach innych niż posix (takich jak tak zwane bashizmy), możesz użyć technik, które nie wymagają rozwidlania zewnętrznych narzędzi, takich jak grep, sed, cut, awk itp., sprawić, że twój skrypt będzie mniej wydajny. Może wydajność i przenośność Posix nie są ważne w twoim przypadku użycia. Ale jeśli tak jest (lub po prostu jest to dobry nawyk), możesz użyć następującej metody opcji rozwijania parametrów , aby wyodrębnić pierwsze dwa znaki zmiennej powłoki:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Wykorzystuje rozwinięcie parametrów „najmniejszy prefiks” w celu usunięcia pierwszych dwóch znaków (to jest ${var#??}część), a następnie rozwinięcie parametrów „najmniejszy sufiks” ( ${var%część) w celu usunięcia tego ciągu składającego się wyłącznie z dwóch pierwszych znaków z oryginału wartość.
Ta metoda została wcześniej opisana w odpowiedzi na pytanie „Powłoka = Sprawdź, czy zmienna zaczyna się od #”. Ta odpowiedź opisuje również kilka podobnych metod rozwijania parametrów, których można użyć w nieco innym kontekście niż ten, który odnosi się do pierwotnego pytania.
Jeśli twój system używa innej powłoki (nie bash), ale twój system ma bash, możesz nadal używać nieodłącznej manipulacji ciągiem bash, wywołując bashzmienną:
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bashwtedy, gdy jeszcze jej nie używasz.
Dla zabawy dodam jeszcze kilka, że choć są zbyt skomplikowane i bezużyteczne, nie zostały wymienione:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
jeśli mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
wydrukowałoby US
gdzie 0 to pozycja początkowa, a 2 to jak odczytać wiele znaków
awk. Przepraszam, na początku nie mogłem powiedzieć.
Czy to jest to, czego szukasz?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'