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;1
vyhovují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
cut
zní jako nástroj pro danou úlohu.