Chci smazat poslední sloupec souboru txt, i když nevím, jaké číslo sloupce je. Jak to mohu udělat?
Příklad:
Vstup:
1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222
A chci, aby byl můj výstup :
1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Komentáře
Odpovědět
S awk:
awk "NF{NF-=1};1" <in >out
nebo:
awk "NF{NF--};1" <in >out
nebo:
awk "NF{--NF};1" <in >out
Ačkoli to vypadá jako vúdú, funguje to. Každý z těchto příkazů awk má tři části.
První je NF, což je předpoklad pro druhou část. NF je proměnná obsahující počet polí v řádku. V AWK jsou věci pravdivé, pokud „nejsou 0 nebo prázdný řetězec "". Druhá část (tedy NF je snížena) nastane, pouze pokud NF není 0.
Druhá část (buď NF-=1 nebo --NF) právě odečítá jeden z proměnné NF. Tím se zabrání vytištění posledního pole, protože když změníte pole (v tomto případě odstraníte poslední pole), awk znovu sestavit $0, ve výchozím nastavení zřetězit všechna pole oddělená mezerou . $0 již neobsahuje poslední pole.
Poslední část je 1. Není to kouzelné, používá se pouze jako výraz, který znamená true. Pokud je výraz awk vyhodnocen jako true bez jakékoli přidružené akce, awk výchozí akce je print $0 .
Komentáře
- @JJoao: Ach, díky, zapomněl jsem na
--. Poznámka, aktuálně potřebujete;1vyhovující POSIX. - Mým původním instinktem by bylo použít smyčku for, ale je to mnohem výstižnější a chytřejší.
- ' Stojí za zmínku, že pokud ' používáte jiný než výchozí oddělovač, ' Budu muset provést nějaké změny. Za předpokladu, že
,je váš oddělovač:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out - Účinkem snižování NF je nedefinované chování POSIX – získáte odlišný výstup podle toho, které awk ' znovu spouštíte. Některá awks odstraní poslední pole, jak chcete, některá neudělají vůbec nic a další mohou nahlásit syntaktickou chybu nebo něco jiného.
Odpovědět
Používání grep s PCRE:
$ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Používání GNU sed:
$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Komentáře
- @ramin Jistě. .mohl byste se na to zeptat jako nová otázka (takhle funguje tento web) 🙂
- @ramin Dává vám nějaké časové omezení nebo jakékoli varování?
- říká, že to není standardní otázka!
- @ramin ok .. dovolte mi kontaktovat administrátora, může vám s tím pomoci .. btw zkontroloval jste nějaké staré QA týkající se vaší otázky? je možné, že otázka je již položena a zodpovězena.
- Nepokládejte ' superzákladní otázky jako " jak mohu v Linuxu přejmenovat název souboru ". Používejte Google.
Odpověď
Používání Perlu:
perl -lane "$,=" ";pop(@F);print(@F)" in
Použití rev + cut:
rev in | cut -d " " -f 2- | rev
Odpověď
Používání GNU sed:
sed -r "s/\s+\S+$//" input.txt
Obecněji, tento pracuje s BSD sed v OSX, stejně jako GNU sed:
sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt
Answer
Pokud je oddělovač vždy jeden znak (takže dva nebo více po sobě jdoucích oddělovačů označuje prázdná pole), můžete head použít pouze první řádek ze vstupního souboru, spočítat oddělovače ( n oddělovače znamená, že počet polí je n+1) a poté použijte cut k tisku z 1 první pole až do n tého pole (předposlední), např. se vstupem odděleným tabulátory:
n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile
nebo např.se souborem csv :
n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile
Některá měřítka spustím později, pokud mám čas, ale s velkým vstupem si myslím, že to řešení by mělo být rychlejší než jiná řešení, která používají regex, protože ten na prvním řádku provádí minimální zpracování, aby získal počet polí, a poté použije cut, které je optimalizováno pro tuto práci.
Odpověď
Přenosně můžete použít některou z těchto možností:
sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file
Odpověď
Použití vim:
Otevřít soubor ve vim
vim <filename>
Přejít na první řádek, pro případ, že by byl kurzor umístěn kdekoli jinde.
gg
Vytvořte makro s názvem „q“ qq, který přejde na konec aktuálního řádku $, poté na poslední mezeru F (velká písmena F, následovaná doslovným VESMÍREM), poté odstraňte z aktuální pozice na konec řádku D přejděte na další řádek j a zastavte nahrávání makra pomocí q.
qq$F Djq
Nyní můžeme naše makro opakovat s @q pro každý řádek.
Můžeme také stisknout @@ opakovat poslední makro nebo ještě snadněji:
99@q
opakovat makro 99krát.
Poznámka: Počet se nesmí přesně shodovat s řádky.
Odpověď
U lidí, kteří mají podobný problém, ale mají různé oddělovače polí, toto awk zachová oddělovač pole správně:
$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar
cutzní jako nástroj pro danou úlohu.