Jak uzyskać ostatni znak ciągu w PHP?

476

Muszę uzyskać ostatni znak ciągu. Powiedzmy, że mam „testery” jako ciąg wejściowy i chcę, aby wynik był „s”. jak mogę to zrobić w PHP?

Parada uliczna
źródło
s($str)->end()Pomocne mogą być informacje zawarte w tej niezależnej bibliotece .
caw

Odpowiedzi:

993
substr("testers", -1); // returns "s"

Lub w przypadku ciągów wielobajtowych:

substr("multibyte string…", -1); // returns "…"
Rich Adams
źródło
114
Jeśli używasz kodowania znaków wielobajtowych, takich jak UTF-8, zamiast tego użyj mb_substr( php.net/mb_substr ).
Gumbo
9
tyle dla mojego substr ($ string, strlen ($ string) -1, 1); Wygląda na to, że wybrałem DŁUGĄ drogę!
jeffkee
4
Potrzebujesz ciągów wielobajtowych, tylko jeśli ciąg jest oceniany jako ciąg binarny. Aka, gdy php nie zna kodowania. W przeciwnym razie typowe nie łańcuchowe funkcje łańcuchowe będą działać dobrze.
Ray Foss,
76
substr($string, -1) 
knittl
źródło
70

Lub przez bezpośredni dostęp do ciągu :

$string[strlen($string)-1];

Zauważ, że to nie działa na łańcuchy wielobajtowe. Jeśli chcesz pracować z ciągiem wielobajtowym, rozważ użycie mb_*rodziny ciągów funkcji.

Od PHP 7.1.0 obsługiwane są również ujemne wskaźniki liczbowe, np. Just $string[-1];

Gordon
źródło
2
Podoba mi się ta odpowiedź w stylu C, zastanawiam się, dlaczego ma tak niewiele głosów pozytywnych.
Valentin Mercier
16
@ValentinMercier: Ponieważ jest to pytanie PHP, a nie C.
Martin Thoma
1
Myślę, że jest to lepsze rozwiązanie, ponieważ pozwala modyfikować postać, podczas gdy podane powyżej rozwiązanie substr nie.
cazort
Pamiętaj, że spowoduje to wyświetlenie powiadomienia, jeśli ciąg znaków będzie pusty.
Scott Buchanan
40

Z PHP 7.1 możesz to zrobić ( Akceptowane rfc dla ujemnych przesunięć łańcucha ):

<?php
$silly = 'Mary had a little lamb';
echo $silly[-20];
echo $silly{-6};
echo $silly[-3];
echo $silly[-15];
echo $silly[-13];
echo $silly[-1];
echo $silly[-4];
echo $silly{-10};
echo $silly[-4];
echo $silly[-8];
echo $silly{3}; // <-- this will be deprecated in PHP 7.4
die();

Pozwolę ci zgadnąć wynik.

Dodałem również to do kodu wydajności ksenonitu z następującymi wynikami:

substr () zajęło 7.0334868431091 sekund

dostęp do tablicy zajął 2.3111131191254 sekund

Bezpośredni dostęp do ciągu (ujemne przesunięcie ciągu) zajął 1,7971360683441 sekund

RyanNerd
źródło
Dziękujemy za opublikowanie testów porównawczych! Jeśli ktoś jest zainteresowany testami porównawczymi C # za zrobienie tego samego, ta strona jest dobra. Wygrał bezpośredni dostęp do ostatniej postaci.
czy możesz wyjaśnić więcej na temat różnic między [] a {} w tym kontekście?
Taufik Nur Rahmanda
2
@TaufikNurRahmanda Technicznie nie ma różnicy między [] a {}. Programiści PHP dali opcję użycia jednego z nich. Aby uzyskać więcej informacji, zobacz: php.net/manual/en/migration71.new-features.php
RyanNerd
co to jest dostęp do tablicy i co to jest bezpośredni dostęp do ciągu? @RyanNerd afaik to 2 takie same rzeczy, nie?
CT.
1
$ string {1} będzie przestarzałe w PHP 7.4 (RFC: wiki.php.net/rfc/deprecate_curly_braces_array_access )
Tony Vlcek
17

Nie mogę zostawiać komentarzy, ale w odniesieniu do odpowiedzi FastTrack pamiętaj również, że zakończenie linii może być tylko jednym znakiem. sugerowałbym

substr(trim($string), -1)

EDYCJA: Mój kod poniżej został edytowany przez kogoś, przez co nie robi tego, co wskazałem. Przywróciłem oryginalny kod i zmieniłem jego sformułowanie, aby było bardziej jasne.

trim(lub rtrim) usunie wszystkie białe znaki, więc jeśli musisz sprawdzić spację, tabulator lub inne białe znaki, najpierw ręcznie zamień różne zakończenia linii:

$order = array("\r\n", "\n", "\r");
$string = str_replace($order, '', $string);
$lastchar = substr($string, -1);
Slashback
źródło
12

Począwszy od PHP 7.1.0, obsługiwane są również ujemne przesunięcia ciągów. Jeśli więc nadążasz za czasem, możesz uzyskać dostęp do ostatniego znaku w ciągu:

$str[-1]

PRÓBNY

Na prośbę @mickmackusa uzupełniam moją odpowiedź możliwymi sposobami zastosowania:

<?php

$str='abcdef';
var_dump($str[-2]); // => string(1) "e"

$str[-3]='.';
var_dump($str);     // => string(6) "abc.ef"

var_dump(isset($str[-4]));  // => bool(true)

var_dump(isset($str[-10])); // => bool(false)
nektobit
źródło
Stosowanie przesunięć ujemnych było techniką wspomnianą wiele lat wcześniej przez RyanNerd. Opublikuj odpowiedź tylko wtedy, gdy masz unikalne i cenne informacje do udostępnienia.
mickmackusa
@mickmackusa Dlaczego napisałeś to tylko dla mnie i zignorowałeś wiele odmian substr ()?
nektobit
Nic osobistego, właśnie zobaczyłem twoją bardzo krótką i zbędną odpowiedź i postanowiłem dmuchnąć w gwizdek. Jeśli masz wrażenie, że nie wnoszą one żadnej wartości, zachęcamy do ujawnienia innych odpowiedzi. Pamiętaj, że dwie odpowiedzi mogą sugerować tę samą technikę, ale każda z nich może być indywidualnie cenna z powodu tego, co zostało wyjaśnione. Jest to miejsce edukacji i wzmocnienia - dodawanie unikalnych informacji do wcześniej oferowanych rozwiązań może być bardzo cenne dla badaczy.
mickmackusa
Na przykład moja odpowiedź została opublikowana miesiąc po opublikowaniu tej samej techniki. Zamierzałem napisać komentarz pod wcześniejszą odpowiedzią, ale kiedy wpisałem wszystkie informacje, które chciałem zaoferować, było to oczywiście zbyt wiele, aby rozsądnie skomentować. Opublikowałem nową odpowiedź i dodałem wiele dodatkowych spostrzeżeń i podstawowych informacji dotyczących techniki oraz zawierałem punkt odniesienia. W ten sposób nie unikalne rozwiązanie może być cenne dla naukowców.
mickmackusa
5

Radzę wybrać rozwiązanie Gordona, ponieważ jest ono bardziej wydajne niż substr ():

<?php 

$string = 'abcdef';
$repetitions = 10000000;

echo "\n\n";
echo "----------------------------------\n";
echo $repetitions . " repetitions...\n";
echo "----------------------------------\n";
echo "\n\n";

$start = microtime(true);
for($i=0; $i<$repetitions; $i++)
    $x = substr($string, -1);

echo "substr() took " . (microtime(true) - $start) . "seconds\n";

$start = microtime(true);
for($i=0; $i<$repetitions; $i++)
    $x = $string[strlen($string)-1];

echo "array access took " . (microtime(true) - $start) . "seconds\n";

die();

wypisuje coś podobnego

 ---------------------------------- 
 10000000 repetitions...
 ----------------------------------

 substr() took 2.0285921096802seconds 
 array access took 1.7474739551544seconds
Ksenonit
źródło
2
To powinien być komentarz do odpowiedzi Gordona.
Goose
1
Potwierdzam to. Im dłuższy ciąg, tym większa różnica w wydajności. W moim teście z 10 znakami substr jest około 20% wolniejszy
Philipp
Nic dziwnego, ponieważ substr () ma narzut wywołania funkcji, a drugą jest bezpośrednia manipulacja ciągiem znaków podobna do „C”. BTW Uruchomiłem ten kod na PHP 7.1-dev z wynikami: substr () zajął 7.090255022049seconds \ dostęp do tablicy zajął 2.3145787715912seconds
RyanNerd
4

Pamiętaj, że jeśli masz ciąg, który został odczytany jako wiersz z pliku tekstowego za pomocą fgets()funkcji, musisz go użyć substr($string, -3, 1), aby uzyskać rzeczywisty znak, a nie część CRLF (Carriage Return Line Feed).

Nie sądzę, żeby osoba, która zadała pytanie, potrzebowała tego, ale dla mnie miałem problem z uzyskaniem tego ostatniego znaku z ciągu z pliku tekstowego, więc jestem pewien, że inni napotkają podobne problemy.

FastTrack
źródło
2

Ostatni znak można znaleźć za pomocą php na wiele sposobów, takich jak substr () i mb_substr () .

Jeśli używasz kodowania znaków wielobajtowych, takich jak UTF-8, użyj mb_substr zamiast substr

Tutaj mogę pokazać oba przykłady:

<?php
    echo substr("testers", -1);
    echo mb_substr("testers", -1);
?>

DEMO NA ŻYWO

Faisal
źródło
1

Ciąg znaków w różnych językach, w tym Cis i PHP, jest również uważany za tablicę znaków.

Wiedząc, że teoretycznie operacje tablicowe powinny być szybsze niż operacje łańcuchowe, które możesz wykonać,

$foo = "bar";


$lastChar = strlen($foo) -1;
echo $foo[$lastChar];

$firstChar = 0;
echo $foo[$firstChar];

Jednak standardowe funkcje tablicy, takie jak

count();

nie będzie działać na łańcuchu.

Petar Atanasow
źródło
-3

Siemano, pobierz tylko pliki php z wybranego katalogu:

$dir    = '/home/zetdoa/ftp/domeny/MY_DOMAIN/projekty/project';
$files = scandir($dir, 1);


foreach($files as $file){
  $n = substr($file, -3);
  if($n == 'php'){
    echo $file.'<br />';
  }
}
ZMORA PROSTO Z KRZOKA
źródło