Seth Kenlon 发布的文章

来学习一下多次执行同一条命令的不同类型的循环。

awk 脚本有三个主要部分:BEGINEND 函数(都可选),用户自己写的每次要执行的函数。某种程度上,awk 的主体部分就是一个循环,因为函数中的命令对每一条记录都会执行一次。然而,有时你希望对于一条记录执行多次命令,那么你就需要用到循环。

有多种类型的循环,分别适合不同的场景。

while 循环

一个 while 循环检测一个表达式,如果表达式为 true 就执行命令。当表达式变为 false 时,循环中断。

#!/bin/awk -f

BEGIN {
        # Loop through 1 to 10

    i=1;
    while (i <= 10) {
        print i, " to the second power is ", i*i;
        i = i+1;
    }
exit;
}

在这个简单实例中,awk 打印了放在变量 i 中的整数值的平方。while (i <= 10) 语句告诉 awk 仅在 i 的值小于或等于 10 时才执行循环。在循环最后一次执行时(i 的值是 10),循环终止。

do-while 循环

do-while 循环执行在关键字 do 之后的命令。在每次循环结束时检测一个测试表达式来决定是否终止循环。仅在测试表达式返回 true 时才会重复执行命令(即还没有到终止循环的条件)。如果测试表达式返回 false,因为到了终止循环的条件所以循环被终止。

#!/usr/bin/awk -f
BEGIN {

        i=2;
        do {
                print i, " to the second power is ", i*i;
                i = i + 1
        }
        while (i < 10)

exit;
}

for 循环

awk 中有两种 for 循环。

一种 for 循环初始化一个变量,检测一个测试表达式,执行变量递增,当表达式的结果为 true 时循环就会一直执行。

#!/bin/awk -f

BEGIN {
    for (i=1; i <= 10; i++) {
        print i, " to the second power is ", i*i;
    }
exit;
}

另一种 for 循环设置一个有连续索引的数组变量,对每一个索引执行一个命令集。换句话说,它用一个数组“收集”每一条命令执行后的结果。

本例实现了一个简易版的 Unix 命令 uniq。通过把一系列字符串作为键加到数组 a 中,当相同的键再次出现时就增加键值,可以得到某个字符串出现的次数(就像 uniq--count 选项)。如果你打印该数组的所有键,将会得到出现过的所有字符串。

用演示文件 colours.txt(前一篇文章中的文件)来举例:

name       color  amount
apple      red    4
banana     yellow 6
raspberry  red    99
strawberry red    3
grape      purple 10
apple      green  8
plum       purple 2
kiwi       brown  4
potato     brown  9
pineapple  yellow 5

这是 awk 版的简易 uniq -c

#! /usr/bin/awk -f

NR != 1 {
    a[$2]++
}
END {
    for (key in a) {
                print a[key] " " key
    }
}

示例数据文件的第三列是第一列列出的条目的计数。你可以用一个数组和 for 循环来按颜色统计第三列的条目。

#! /usr/bin/awk -f

BEGIN {
    FS=" ";
    OFS="\t";
    print("color\tsum");
}
NR != 1 {
    a[$2]+=$3;
}
END {
    for (b in a) {
        print b, a[b]
    }
}

你可以看到,在处理文件之前也需要在 BEFORE 函数(仅仅执行一次)中打印一列表头。

循环

在任何编程语言中循环都是很重要的一部分,awk 也不例外。使用循环你可以控制 awk 脚本怎样去运行,它可以统计什么信息,还有它怎么去处理你的数据。我们下一篇文章会讨论 switchcontinuenext 语句。


via: https://opensource.com/article/19/11/loops-awk

作者:Seth Kenlon 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如果你是 Linux 资深用户,则可能会有这些共同倾向。

Linux 用户千差万别,但是我们许多人都有一些相同的习惯。你可能没有本文列出的任何特征,而且如果你是个 Linux 新用户,你可能还不能理解这些特征……

下面是你可能是 Linux 用户的六个特征。

1、理所当然,纪元始于 1970 年 1 月 1 日

关于 Unix 计算机时钟为何在重置时总是将其设置回 1970-01-01 的传闻有很多。但有点令人感到乏味的事实是,Unix “纪元”是用于同步的通用且简单的参考点。例如,万圣节在儒略历中是今年的 304 日,但我们通常将该节日称为 “31 号”。我们知道指的是哪个月的 31 号,因为我们有个共同的参考点:我们知道万圣节在 10 月庆祝,而 10 月是一年中的第十个月,并且我们知道前面每一个月包含多少天。没有这些值,虽然我们可以使用传统的计时方法(如月相)来跟踪特殊的季节性事件,但是计算机显然不具备这种能力。

计算机需要确定且明确定义的值,因此将值 1970-01-01T00:00:00Z 选择为 Unix 纪元的开始。每当 POSIX 计算机的时间不准确时,诸如网络时间协议(NTP)之类的服务就可以向其提供自 1970-01-01T00:00:00Z 以来的秒数,计算机可以将其转换为人类易于识别的日期。

日期和时间是在计算中要追踪的著名的复杂事物,主要是因为几乎所有标准都有例外。一个月并不总是有 30 天,一年也不总是有 365 天,甚至每年有多少秒钟也往往会有所不同。如果你正在寻找一个有趣而令人沮丧的编程练习,那么请尝试编程一个可靠的日历应用程序!

2、输入超过两个字母你就会觉得麻烦

众所周知,最常见的 Unix 命令都超简短。除了 cdlsmv 之类的命令外,还有一个命令简直不能再短了:w(它根据 /var/run/utmp 文件显示当前谁登录了)。

一方面,极短的命令似乎很不直观。新用户可能不会猜测到键入 ls 列出 list 目录。但是,一旦学习命令,它们肯定是越短越好。如果你整天都在终端上度过,那么你键入的击键次数越少就意味着你可以有更多的时间来完成工作。

幸运的是,单字母命令并不太多,因此你可以使用大多数字母作为别名。例如,我经常使用 Emacs,以至于我觉得 emacs 的输入时间太长,因此通过将下面这行添加到 .bashrc 文件中,将其别名为 e

alias e='emacs'

你也可以临时为命令添加别名。例如,如果你在解决网络问题时发现自己反复运行 firewall-cmd,则可以为当前会话创建别名:

$ alias f='firewall-cmd'
$ f
usage: see firewall-cmd man page
No option specified.

只要你打开着终端,你的别名就会一直存在。当终端一旦关闭,它便会被遗忘。

3、做任何事都不应该单击两次以上

Linux 用户喜欢效率。尽管并非每个 Linux 用户都总是急于完成工作,但 Linux 桌面中有一些旨在减少完成任务所需的操作数量的惯例。这里有些例子。

  • 在 KDE 文件管理器 Dolphin 中,单击即可打开文件或目录。假定如果要选择一个文件,则可以单击并拖动,也可以 Ctrl + 点击。这可能会使习惯于双击所有内容的用户感到困惑,但是一旦你尝试了单击操作,通常就无法返回费力的双击操作。
  • 在大多数 Linux 桌面上,单击鼠标中键可粘贴剪贴板的最新内容。
  • 在许多 Linux 桌面上,可以通过按 AltCtrlShift 键来修改拖动动作。例如,Alt + 拖动 在 KDE 中移动窗口,而 GNOME 中的 Ctrl + 拖动 会复制文件而不是移动。

4、任何操作你都不会执行三次以上,因为第三次时你已经将它自动化了

请原谅我有点夸张,但是许多 Linux 用户期望他们的计算机比他们更努力地工作。虽然学习如何自动执行常见任务需要花费时间,但在 Linux 上它往往比在其它平台上更容易,因为 Linux 终端和 Linux 操作系统是如此紧密地集成在一起。最容易自动化的是你在终端中已经执行的操作,因为命令只是你在解释器中键入的字符串,而该解释器(终端)不会在乎你是手动键入字符串还是将其指向一个脚本。

例如,如果你发现自己经常将一组文件从一个位置移动到另一个位置,则或许可以将相同的指令序列用作一个脚本,你可以使用单个命令来触发该脚本。假设你每天早上手动执行此操作:

$ cd Documents
$ trash reports-latest.txt
$ wget myserver.local/reports/daily/report-latest.txt
$ cp report-latest.txt reports_daily/2019-31-10.log

这是一个简单的序列,但是每天重复一次并不是消磨时间的最有效方法。做一点点抽象,你可以使用一个简单的脚本将其自动化:

#!/bin/sh

trash $HOME/Documents/reports-latest.txt

wget myserver.local/reports/daily/report-latest.txt \
  -P $HOME/Documents/udpates_daily/`date --iso-8601`.log

cp $HOME/Documents/udpates_daily/`date --iso-8601`.log \
  $HOME/Documents/reports-latest.txt

你可以把你的脚本叫做 get-reports.sh 并在每天早晨手动启动它,或者甚至可以将其输入到 crontab 中,以便计算机可以执行此任务而无需你进行任何干预。

对于新用户来说,这可能会有点困扰,因为什么和什么是一体的并不总是很明显。例如,如果你经常发现自己打开图像并将其按比例缩小 50%,那么你可能习惯于执行以下操作:

  1. 打开你的照片查看器或编辑器
  2. 缩放图像
  3. 将图像导出为修改后的文件
  4. 关闭应用程序

如果你一天要做几次,你可能会对这种重复感到厌倦。但是,由于你是在图形用户界面(GUI)中执行这些操作的,因此你需要知道如何对 GUI 编写脚本以使其自动化。某些应用程序,例如 GIMP,具有丰富的脚本接口,但是其过程显然不同于仅修改一堆命令并将其存储到文件中那么简单。

再说一次,有时在命令行中有与你在 GUI 中所做的等效的操作。将文档从一种文本格式转换为另一种格式可以使用 Pandoc,处理图像可以使用 Image Magick,音乐和视频也可以通过命令行进行编辑和转换,等等。最大的问题是你需要知道要查找什么,通常是学习新的(有时是复杂的)命令。但是,在终端中按比例缩小图像比在 GUI 中显然更简单:

#!/bin/sh

convert "${1}" -scale 50% `basename "${1}" .jpg`_50.jpg

这些麻烦、重复的任务值得研究。你永远不知道你的工作让计算机做起来是有多么的简单和快捷!

5、发行版之间跳来跳去

我在家里是一个热情的 Slackware 用户,而在工作时是一个 RHEL 用户。实际上,这不是事实,我现在在工作时是 Fedora 用户。除了有时候我使用 CentOS,偶尔我还会运行 Mageia

 title=

运行在 PowerPC64 机器上的 Debian

发行版好不好无关紧要,成为 Linux 用户的极致乐趣之一是可以自由决定运行哪个发行版。乍一看,它们基本相同,令人耳目一新。但是根据你的心情,你可能更喜欢 CentOS 的稳定性而不是 Fedora 的不断更新,或者你可能有一天会真正享受 Mageia 的集中控制中心,然后又对原始的 Debian 配置文件进行模块化乐在其中,而有时你又会完全转向其他操作系统。

 title=

OpenBSD,不是 Linux 发行版

关键是,Linux 发行版是激情项目,成为其他人的开源激情的一部分很有趣。

6、你对开源充满热情

无论你的经验如何,如果你是 Linux 用户,那么你无疑会对开源充满热情。无论你是每天通过共创艺术品还是代码来表达你的热情,还是将其升华到只在自由而自在的环境中完成工作,你都生活并构筑于开源之上。因为有了千千万万个你,所以有了开源社区,社区因你而变得更加丰富。

有太多的东西我没有提到。作为 Linux 用户,还有什么可以出卖你的身份?让我们在评论中知道!


via: https://opensource.com/article/19/10/signs-linux-user

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如果你才刚开始学习 Java 编程,这里有七个你需要知道的基础知识。

Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Java 的最大优势是,它运行在一个 Java 虚拟机(JVM)中,这是一个翻译 Java 代码为与操作系统兼容的字节码的层。只要有 JVM 存在于你的操作系统上 —— 不管这个操作系统是在一个服务器(或“无服务器”,也是同样的)、桌面电脑、笔记本电脑、移动设备,或嵌入式设备 —— 那么,Java 应用程序就可以运行在它上面。

这使得 Java 成为程序员和用户的一种流行语言。程序员知道,他们只需要写一个软件版本就能最终得到一个可以运行在任何平台上的应用程序;用户知道,应用程序可以运行在他们的计算机上,而不用管他们使用的是什么样的操作系统。

很多语言和框架是跨平台的,但是没有实现同样的抽象层。使用 Java,你针对的是 JVM,而不是操作系统。对于程序员,当面对一些编程难题时,这是阻力最小的线路,但是它仅在当你知道如何编程 Java 时有用。如果你刚开始学习 Java 编程,这里有你需要知道的七个基础的提示。

但是,首先,如果你不确定是否你安装了 Java ,你可以在一个终端(例如 BashPowerShell)中找出来,通过运行:

$ java --version
openjdk 12.0.2 2019-07-16
OpenJDK Runtime Environment 19.3 (build 12.0.2+9)
OpenJDK 64-Bit Server VM 19.3 (build 12.0.2+9, mixed mode, sharing)

如果你得到一个错误,或未返回任何东西,那么你应该安装 Java 开发套件(JDK)来开始 Java 开发。或者,安装一个 Java 运行时环境(JRE),如果你只是需要来运行 Java 应用程序。

1、Java 软件包

在 Java 语言中,相关的类被分组到一个软件包中。当你下载 JDK 时所获得的 Java 基础库将被分组到以 javajavax 开头的软件包中。软件包提供一种类似于计算机上的文件夹的功能:它们为相关的元素提供结构和定义(以编程术语说,命名空间)。额外的软件包可以从独立开发者、开源项目和商业供应商获得,就像可以为任何编程语言获得库一样。

当你写一个 Java 程序时,你应该在你的代码是顶部声明一个软件包名称。如果你只是编写一个简单的应用程序来入门 Java,你的软件包名称可以简单地用你的项目名称。如果你正在使用一个 Java 集成开发环境,如 Eclipse,当你启动一个新的项目时,它为你生成一个合乎情理的软件包名称。

package helloworld;

/**
 * @author seth
 * An application written in Java.
 */

除此之外,你可以通过查找它相对于你的项目整体的路径来确定你的软件包名称。例如,如果你正在写一组类来帮助游戏开发,并且该集合被称为 jgamer,那么你可能在其中有一些唯一的类。

package jgamer.avatar;

/**
 * @author seth
 * An imaginary game library.
 */

你的软件包的顶层是 jgamer,并且在其内部中每个软件包都是一个独立的派生物,例如 jgamer.avatarjgamer.score 等等。在你的文件系统里,其目录结构反映了这一点,jgamer 是包含文件 avatar.javascore.java 的顶级目录。

2、Java 导入

作为一名通晓多种语言的程序员,最大的乐趣是找出是否用 includeimportuserequire,或一些其它术语来引入你不管使用何种编程语言编写的库。在 Java 中,顺便说一句,当导入你的代码的需要的库时,使用 import 关键字。

package helloworld;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * @author seth
 * A GUI hello world.
 */

导入是基于该环境的 Java 路径。如果 Java 不知道 Java 库存储在系统上的何处,那么,就不能成功导入。只要一个库被存储在系统的 Java 路径中,那么导入能够成功,并且库能够被用于构建和运行一个 Java 应用程序。

如果一个库并不在 Java 路径中(因为,例如,你正在写你自己的库),那么该库可以与你的应用程序绑定在一起(协议许可),以便导入可以按预期地工作。

3、Java 类

Java 类使用关键字 public class 声明,以及一个唯一的对应于它的文件名的类名。例如,在项目 helloworld 中的一个文件 Hello.java 中:

package helloworld;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * @author seth
 * A GUI hello world.
 */

public class Hello {
        // this is an empty class
}

你可以在一个类内部声明变量和函数。在 Java 中,在一个类中的变量被称为字段

4、Java 方法

Java 的方法本质上是对象中的函数。基于预期返回的数据类型(例如 voidintfloat 等等),它们被定义为 public(意味着它们可以被任何其它类访问)或 private(限制它们的使用)。

    public void helloPrompt(ActionEvent event) {
        String salutation = "Hello %s";
 
        string helloMessage = "World";
        message = String.format(salutation, helloMessage);
        JOptionPane.showMessageDialog(this, message);
    }
 
    private int someNumber (x) {
        return x*2;
    }

当直接调用一个方法时,以其类和方法名称来引用。例如,Hello.someNumber 指向在 Hello 类中的 someNumber 方法。

5、static

Java 中的 static 关键字使代码中的成员可以独立于包含其的对象而被访问。

在面向对象编程中,你编写的代码用作“对象”的模板,这些对象在应用程序运行时产生。例如,你不需要编写一个具体的窗口,而是编写基于 Java 中的窗口类的窗口实例(并由你的代码修改)。由于在应用程序生成它的实例之前,你编写的所有代码都不会“存在”,因此在创建它们所依赖的对象之前,大多数方法和变量(甚至是嵌套类)都无法使用。

然而,有时,在对象被通过应用程序创建前,你需要访问或使用其中的数据。(例如,除非事先知道球是红色时,应用程序无法生成一个红色的球)。对于这些情况,请使用 static 关键字。

6、try 和 catch

Java 擅长捕捉错误,但是,只有你告诉它遇到错误时该做什么,它才能优雅地恢复。在 Java 中,尝试执行一个动作的级联层次结构以 try 开头,出现错误时回落到 catch,并以 finally 结束。如果 try 子句失败,则将调用 catch,最后,不管结果如何,总是由 finally 来执行一些合理的动作。这里是一个示例:

try {
        cmd = parser.parse(opt, args); 
       
        if(cmd.hasOption("help")) {
                HelpFormatter helper = new HelpFormatter();
                helper.printHelp("Hello <options>", opt);
                System.exit(0);
                }
        else {
                if(cmd.hasOption("shell") || cmd.hasOption("s")) {
                String target = cmd.getOptionValue("tgt");
                } // else
        } // fi
} catch (ParseException err) {
        System.out.println(err);
        System.exit(1);
        } //catch
        finally {
                new Hello().helloWorld(opt);
        } //finally
} //try

这是一个健壮的系统,它试图避免无法挽回的错误,或者,至少,为你提供让用户提交有用的反馈的选项。经常使用它,你的用户将会感谢你!

7、运行 Java 应用程序

Java 文件,通常以 .java 结尾,理论上说,可以使用 java 命令运行。然而,如果一个应用程序很复杂,运行一个单个文件是否会产生有意义的结果是另外一个问题。

来直接运行一个 .java 文件:

$ java ./Hello.java

通常,Java 应用程序以 Java 存档(JAR)文件的形式分发,以 .jar 结尾。一个 JAR 文件包含一个清单文件(可以指定主类、项目结构的一些元数据),以及运行应用程序所需的所有代码部分。

要运行一个 JAR 文件,你可以双击它的图标(取决于你的操作系统设置),你也可以从终端中启动它:

$ java -jar ./Hello.jar

适合所有人的 Java

Java 是一种强大的语言,由于有了 OpenJDK 项目及其它的努力,它是一种开放式规范,允许像 IcedTeaDalvikKotlin 项目的茁壮成长。学习 Java 是一种准备在各种行业中工作的好方法,而且,使用 Java 的理由很多


via: https://opensource.com/article/19/10/java-basics

作者:Seth Kenlon 选题:lujun9972 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在桌面上拥抱 Java 应用程序,然后在所有桌面上运行它们。

无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序,或者使用 Fedora 上的 DNF 或 Mac 上的 Brew 这样的软件包管理器进行安装,而有时你可能会从网站上下载可执行文件或安装程序。因为 Java 是这么多流行的应用程序的后端,所以最好了解安装它的不同方法。好消息是你有很多选择,本文涵盖了所有这些内容。

坏消息是 Java 太大,我说的不仅仅是文件大小。Java 是一种开放源代码语言和规范,这意味着从理论上讲,任何人都可以创建它的实现版本。这意味着,在安装任何东西之前,必须确定要安装的 Java 发行版。

我需要 JVM 还是 JRE 或者 JDK?

Java 大致分为两个下载类别。 Java 虚拟机 Java Virtual Machine (JVM)是运行时组件;它是使 Java 应用程序能够在计算机上启动和运行的“引擎”。它包含在 Java 运行时环境 Java Runtime Environment (JRE)中。

Java 开发工具包 Java Development Kit (JDK)是一个开发工具包:你可以将其视为一个车库,修理工可以坐在那里进行调整、修理和改进。JDK 包含 Java 运行时环境(JRE)。

以下载来说,这意味着:

  • 如果你是希望运行 Java 应用程序的用户,则只需 JRE(包括了 JVM)。
  • 如果你是希望使用 Java 进行编程的开发人员,则需要 JDK(包括 JRE 库,而 JRE 库又包括 JVM)。 ### OpenJDK、IcedTea 和 OracleJDK 有什么不同?

太阳微系统 Sun Microsystems 被 Oracle 收购时,Java 是该交易的主要部分。幸运的是,Java 是一种开源技术,因此,如果你对 Oracle 维护该项目的方式不满意,则可以选择其他方法。Oracle 将专有组件与 Java 下载捆绑在一起,而 OpenJDK 项目是完全开源的。

IcedTea 项目本质上是 OpenJDK,但其目标是使用户在使用完全自由开源的工具时更容易构建和部署 OpenJDK。

(LCTT 译注:阿里巴巴也有一个它自己维护的 Open JDK 发行版“ 龙井 Dragonwell ”。以下引自其官网:“Alibaba Dragonwell 是一款免费的,生产就绪型 Open JDK 发行版,提供长期支持,包括性能增强和安全修复。……Alibaba Dragonwell 作为 Java 应用的基石,支撑了阿里经济体内所有的 Java 业务。Alibaba Dragonwell 完全兼容 Java SE 标准,……”)

我应该安装哪个 Java?

如果你对这些选择感到不知所措,那么简单的答案就是你应该安装的 Java 实现应该是最容易安装的那个。当应用程序告诉你需要 Java 12,但你的存储库中只有 Java 8 时,可以安装可以从可靠来源中找到的 Java 12 的任何实现。在 Linux 上,你可以一次安装几个不同版本的 Java,它们不会互相干扰。

如果你是需要选择使用哪个版本的开发人员,则应考虑所需的组件。如果选择 Oracle 的版本,请注意,软件包中包含专有的插件和字体,可能会影响你分发你的应用程序。在 IcedTea 或 OpenJDK 上进行开发是最安全的。

从存储库安装 OpenJDK?

现在,你已经知道要选择什么了,你可以使用软件包管理器搜索 OpenJDK 或 IcedTea,然后安装所需的版本。有些发行版使用关键字 latest 来指示最新版本,这通常是你要运行的应用程序所需要的。根据你使用的软件包管理器,你甚至可以考虑使用 grep 过滤搜索结果以仅包括最新版本。例如,在 Fedora 上:

$ sudo dnf search openjdk | grep latest | cut -f1 -d':'

java-latest-openjdk-demo.x86_64
java-openjdk.i686
java-openjdk.x86_64
java-latest-openjdk-jmods.x86_64
java-latest-openjdk-src.x86_64
java-latest-openjdk.x86_64
[...]

只有当你尝试运行的应用程序坚持要求你使用 Java 的旧版本时,你才应该看看 latest 之前的版本。

在 Fedora 或类似系统上安装 Java:

$ sudo dnf install java-latest-openjdk

如果你的发行版不使用 latest 标签,则可以使用其他关键字,例如 default。以下是在 Debian 上搜索 OpenJDK 的信息:

$ sudo apt search openjdk | less
default-jdk
  Standard Java development kit

default-jre
  Standard Java runtime

openjdk-11-jdk
  OpenJDK development kit (JDK)

[...]

在这种情况下,default-jre 软件包适合用户,而 default-jdk 则适合开发人员。

例如,要在 Debian 上安装 JRE:

$ sudo apt install default-jre

现在已安装好 Java。

你的存储库中可能有许多与 Java 相关的软件包。要搜索 OpenJDK,如果你是用户,则查找最新的 JRE 或 JVM,如果你是开发人员,则查找最新的 JDK。

从互联网上安装 Java

如果在存储库中找不到 JRE 或 JDK,或者找不到满足你需求的 JRE 或 JDK,则可以从互联网上下载开源的 Java 软件包。你可以在 openjdk.java.net 中找到需要手动安装的 tar 形式的 OpenJDK 下载文件,或者可以从 Azul 下载 tar 形式的 Zulu 社区版或其可安装的 RPM 或 DEB 软件包。

从 TAR 文件安装 Java

如果从 Java.net 或 Azul 下载 TAR 文件,则必须手动安装。这通常称为“本地”安装,因为你没有将 Java 安装到“全局”位置。你可以在 PATH 中选择一个合适的位置。

如果你不知道 PATH 中包含什么,请查看一下以找出:

$ echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/seth/bin

在此示例 PATH 中,位置 /usr/local/bin/home/seth/bin 是不错的选择。如果你是计算机上的唯一用户,那么你自己的家目录就很有意义。如果你的计算机上有很多用户,则最好选择一个通用位置,例如 /usr/local/opt

如果你无权访问需要 sudo 权限的 /usr/local 之类的系统级目录,则可以在你自己的家目录中创建一个本地 bin(意思是 “ 二进制 binary ”,而不是“ 垃圾箱 waste bin ”)或 Applications 文件夹:

$ mkdir ~/bin

如果它不在你的 PATH 中,请将其添加到其中:

$ echo PATH=$PATH:$HOME/bin &gt;&gt; ~/.bashrc
$ source ~/.bashrc

最后,将压缩包解压缩到你选择的目录中。

$ tar --extract --file openjdk*linux-x64_bin.tar.gz --directory=$HOME/bin

Java 现在安装好了。

从 RPM 或 DEB 安装 Java

如果从 Azul.com 下载 RPM 或 DEB 文件,则可以使用软件包管理器进行安装。

对于 Fedora、CentOS、RHEL 等,请下载 RPM 并使用 DNF 进行安装:

$ sudo dnf install zulu*linux.x86_64.rpm

对于 Debian、Ubuntu、Pop\_OS 和类似发行版,请下载 DEB 软件包并使用 Apt 安装它:

$ sudo dpkg -i zulu*linux_amd64.deb

Java 现在安装好了。

用 alternatives 安装你的 Java 版本

一些应用程序是为特定版本的 Java 开发的,不能与其他任何版本一起使用。这种情况很少见,但确实会发生,在 Linux 上,你可以使用本地安装方法(请参阅上面“从 TAR 文件安装 Java”一节)或使用 alternatives 应用程序来解决此冲突。

alternatives 命令会查找 Linux 系统上安装的应用程序,并让你选择要使用的版本。有些发行版,例如 Slackware,不提供 alternatives 命令,因此你必须使用本地安装方法。在 Fedora、CentOS 和类似的发行版上,该命令是 alternatives。在 Debian、Ubuntu 和类似的系统上,该命令是 update-alternatives

要获取当前已安装在 Fedora 系统上的应用程序的可用版本列表:

$ alternatives --list

在 Debian 上,你必须指定可供替代的应用程序:

$ update-alternatives --list java

在 Fedora 上选择要使系统将哪个版本作为默认版本:

$ sudo alternatives --config java

在 Debian 上:

$ sudo updates-alternatives --config java

你可以根据需要运行的应用程序,根据需要更改默认的 Java 版本。

运行 Java 应用

Java 应用程序通常以 JAR 文件的形式分发。根据你安装 Java 的方式,你的系统可能已经为运行 Java 应用程序配置好了,这使你只需双击应用程序图标(或从应用程序菜单中选择它)即可运行。如果必须执行未与系统其余部分集成的本地 Java 安装,则可以直接从终端启动 Java 应用程序:

$ java -jar ~/bin/example.jar &

Java 是个好东西

Java 是少数将跨平台开发放在首位的编程环境之一。没有什么比问一个应用程序是否能在你的平台上运行然后发现该应用程序是用 Java 编写要让人感到松一口气的了。它是如此简单,无论你是开发人员还是用户,你都可以摆脱任何平台上的焦虑。在桌面上拥抱 Java 应用程序,然后在所有桌面上运行它们吧。


via: https://opensource.com/article/19/11/install-java-linux

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

NetBSD 的软件包管理器通用、灵活又容易。下面是如何使用它。

NetBSD 以能在几乎所有平台上运行而闻名,但你知道它第二有名的 pkgsrc 包管理器吗?像 NetBSD 一样,pkgsrc 基本上可以在任何系统上运行,或者至少在任意 Unix 和类 Unix 的系统上上运行。你可以在 BSD、Linux、Illumos、Solaris 和 Mac 上安装 pkgsrc。它总共支持 20 多种操作系统。

为什么使用 pkgsrc?

除了 MacOS 之外,所有 Unix 操作系统均自带包管理器。你不一定需要 pkgsrc,但这可能是你想尝试的三个重要原因:

  • 打包。如果你对打包感到好奇,但尚未尝试自己创建一个软件包,那么 pkgsrc 是一个相对简单的系统,尤其是如果你已经熟悉 Makefile 和类似 GNU Autotools 之类的构建系统时。
  • 通用。如果你使用多个操作系统或发行版,那么可能会遇到每个系统的包管理器。你可以在不同的系统上使用 pkgsrc,以便你为一个系统打包了程序,就为所有系统打包了。
  • 灵活。在许多打包系统中,如何选择二进制包或源码包并不总是很明显。使用 pkgsrc,区别很明显,两种安装方法都一样容易,并且都可以为你解决依赖关系。

如何安装 pkgsrc

无论你使用的是 BSD、Linux、Illumos、Solaris 还是 MacOS,安装过程都基本相同:

  1. 使用 CVS 检出 pkgsrc 树
  2. 引导 pkgsrc 系统
  3. 安装软件包

使用 CVS 检出 pkgsrc 树

在 Git 和 Subversion 之前,就有了 CVS。要检出代码你无需了解 CVS 太多,如果你习惯 Git,那么可以将 检出 checkout 称为 克隆 clone 。当你用 CVS 检出 pkgsrc 时,你就下载了详细说明如何构建每个软件包的“ 配方 recipes ”。它有很多文件,但是它们都很小,因为你实际上并没有拉取每个包的源码,而只有按需构建时需要的构建基础架构和 Makefile。使用 CVS,你可以轻松地在新版本发布时更新 pkgsrc 检出。

pkgsrc 文档建议将其源码树放在 /usr 目录下,因此你必须使用 sudo(或成为 root)运行此命令:

$ cd /usr
$ sudo cvs -q -z2 -d [email protected]:/cvsroot checkout -r pkgsrc-2019Q3 -P pkgsrc

在我撰写本文时,最新版本是 2019Q3。请检查 pkgsrc.org 主页的新闻部分或 NetBSD文档,以确定最新版本。

引导 pkgsrc

pkgsrc 树复制到你的计算机后,你会看到一个充满构建脚本的 /usr/pkgsrc 目录。在使用之前,你必须引导 pkgsrc,以便你可以轻松地访问构建和安装软件所需的相关命令。

引导 pkgsrc 的方式取决于你所使用操作系统。

对于 NetBSD,你只需使用捆绑的引导器:

# cd pkgsrc/bootstrap
# ./bootstrap

在其他系统上,还有更好的方法,包括一些自定义功能,它是由 Joyent 提供的。要了解运行的确切命令,请访问 pkgsrc.joyent.com。比如,在 Linux(Fedora、Debian、Slackware 等)上:

$ curl -O https://pkgsrc.joyent.com/packages/Linux/el7/bootstrap/bootstrap-trunk-x86_64-20170127.tar.gz
$ BOOTSTRAP_SHA="eb0d6911489579ca893f67f8a528ecd02137d43a"

尽管路径暗示文件适用于 RHEL 7,但二进制文件往往与所有(最前沿的 Linux 发行版)兼容。如果你发现二进制文件与你的发行版不兼容,你可以选择从源码构建。

验证 SHA1 校验和:

$ echo "${BOOTSTRAP_SHA}" bootstrap-trunk*gz > check-shasum
sha1sum -c check-shasum

你还可以验证 PGP 签名:

$ curl -O https://pkgsrc.joyent.com/packages/Linux/el7/bootstrap/bootstrap-trunk-x86_64-20170127.tar.gz.asc
$ curl -sS https://pkgsrc.joyent.com/pgp/56AAACAF.asc | gpg --import
$ gpg --verify ${BOOTSTRAP_TAR}{.asc,}

当你确认你已有正确的引导套件,将其安装到 /usr/pkg

sudo tar -zxpf ${BOOTSTRAP_TAR} -C /

它为你提供了通常的 pkgsrc 命令。将这些位置添加到你的 PATH 环境变量中

$ echo "PATH=/usr/pkg/sbin:/usr/pkg/bin:$PATH" >> ~/.bashrc
$ echo "MANPATH=/usr/pkg/man:$MANPATH" >> ~/.bashrc

如果你宁愿使用 pkgsrc 而不依赖于 Joyent 的构建,那么只需运行 pkgsrc 源码树的引导脚本即可。在运行特定于系统的脚本之前,请先阅读 bootstrap 目录中相关 README 文件。

 title=

如何使用 pkgsrc 安装软件

使用 pkgsrc 安装预编译的二进制文件(就像使用 DNF 或 Apt 一样)是很容易的。二进制安装的命令是 pgkin,它有自己的专门网站 pkgin.net。对于任何用过 Linux 的人来说,这个过程应该感觉相当熟悉。

要搜索 tmux 包:

$ pkgin search tmux

要安装 tmux 包:

$ sudo pkgin install tmux

pkgin 命令的目的是模仿典型的 Linux 包管理器的行为,因此有选项可以列出可用的包、查找包提供的特定可执行文件,等等。

如何使用 pkgsrc 从源码构建

然而,pkgsrc 真正强大的地方是方便地从源码构建包。你在第一步中检出了所有 20000 多个构建脚本,你可以直接进入 pkgsrc 源码树来访问这些脚本。

例如,要从源码构建 tcsh,首先找到构建脚本:

$ find /usr/pkgsrc -type d -name "tcsh"
/usr/pkgsrc/shells/tcsh

接下来,进入源码目录:

$ cd /usr/pgksrc/shells/tcsh

构建脚本目录包含许多文件来帮助在你的系统上构建应用,但值得注意的是,这里面有包含了软件说明的 DESCR 文件,以及触发构建的 Makefile

$ ls
CVS    DESCR     Makefile
PLIST  distinfo  patches
$ cat DESCR
TCSH is an extended C-shell with many useful features like
filename completion, history editing, etc.
$

准备就绪后,构建并安装:

$ sudo bmake install

pkgsrc 系统使用 bmake 命令(在第一步检出 pkgsrc 后提供),因此请务必使用 bmake(而不是出于习惯使用 make)。

如果要为多个系统构建,那么你可以创建一个包,而不是立即安装:

$ cd /usr/pgksrc/shells/tcsh
$ sudo bmake package
[...]
=> Creating binary package in /usr/pkgsrc/packages/All/tcsh-X.Y.Z.tgz

pkgsrc 创建的包是标准的 tarball,但它可以方便地通过 pkg_add 安装:

$ sudo pkg_add /usr/pkgsrc/packages/All/tcsh-X.Y.Z.tgz
tcsh-X.Y.Z: adding /usr/pkg/bin/tcsh to /etc/shells
$ tcsh
localhost%

pkgsrc 的 pkgtools 集合提供 pkg_addpkg_infopkg_adminpkg_createpkg_delete 命令,来帮助管理你在系统上构建和维护软件包。

pkgsrc,易于管理

pkgsrc 系统提供了直接,容易上手的软件包管理方法。如果你正在寻找一个不妨碍你并且可以定制的包管理器,请在任何运行 Unix 或类 Unix 的系统上试试 pkgsrc。


via: https://opensource.com/article/19/11/pkgsrc-netbsd-linux

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这个系列的第二篇,我们会学习字段,记录和一些非常有用的 Awk 变量。

Awk 有好几个变种:最早的 awk,是 1977 年 AT&T 贝尔实验室所创。它还有一些重构版本,例如 mawknawk。在大多数 Linux 发行版中能见到的,是 GNU awk,也叫 gawk。在大多数 Linux 发行版中,awkgawk 都是指向 GNU awk 的软链接。输入 awk,调用的是同一个命令。GNU awk 用户手册中,能看到 awkgawk 的全部历史。

这一系列的第一篇文章 介绍了 awk 命令的基本格式:

$ awk [选项] '模式 {动作}' 输入文件

awk 是一个命令,后面要接选项 (比如用 -F 来定义字段分隔符)。想让 awk 执行的部分需要写在两个单引号之间,至少在终端中需要这么做。在 awk 命令中,为了进一步强调你想要执行的部分,可以用 -e 选项来突出显示(但这不是必须的):

$ awk -F, -e '{print $2;}' colours.txt
yellow
blue
green
[...]

记录和字段

awk 将输入数据视为一系列记录,通常是按行分割的。换句话说,awk 将文本中的每一行视作一个记录。每一记录包含多个字段。一个字段由字段分隔符分隔开来,字段是记录的一部分。

默认情况下,awk 将各种空白符,如空格、制表符、换行符等视为分隔符。值得注意的是,在 awk 中,多个空格将被视为一个分隔符。所以下面这行文本有两个字段:

raspberry red

这行也是:

tuxedo                  black

其他分隔符,在程序中不是这么处理的。假设字段分隔符是逗号,如下所示的记录,就有三个字段。其中一个字段可能会是 0 个字节(假设这一字段中不包含隐藏字符)

a,,b

awk 程序

awk 命令的程序部分是由一系列规则组成的。通常来说,程序中每个规则占一行(尽管这不是必须的)。每个规则由一个模式,或一个或多个动作组成:

模式 { 动作 }

在一个规则中,你可以通过定义模式,来确定动作是否会在记录中执行。模式可以是简单的比较条件、正则表达式,甚至两者结合等等。

这个例子中,程序只会显示包含单词 “raspberry” 的记录:

$ awk '/raspberry/ { print $0 }' colours.txt
raspberry red 99

如果没有文本符合模式,该动作将会应用到所有记录上。

并且,在一条规则只包含模式时,相当于对整个记录执行 { print },全部打印出来。

Awk 程序本质上是数据驱动的,命令执行结果取决于数据。所以,与其他编程语言中的程序相比,它还是有些区别的。

NF 变量

每个字段都有指定变量,但针对字段和记录,也存在一些特殊变量。NF 变量,能存储 awk 在当前记录中找到的字段数量。其内容可在屏幕上显示,也可用于测试。下面例子中的数据,来自上篇文章文本

$ awk '{ print $0 " (" NF ")" }' colours.txt
name       color  amount (3)
apple      red    4 (3)
banana     yellow 6 (3)
[...]

awkprint 函数会接受一系列参数(可以是变量或者字符串),并将它们拼接起来。这就是为什么在这个例子里,每行结尾处,awk 会以一个被括号括起来的整数表示字段数量。

NR 变量

另外,除了统计每个记录中的字段数,awk 也统计输入记录数。记录数被存储在变量 NR 中,它的使用方法和其他变量没有任何区别。例如,为了在每一行开头显示行号:

$ awk '{ print NR ": " $0 }' colours.txt
1: name       color  amount
2: apple      red    4
3: banana     yellow 6
4: raspberry  red    3
5: grape      purple 10
[...]

注意,写这个命令时可以不在 print 后的多个参数间添加空格,尽管这样会降低可读性:

$ awk '{print NR": "$0}' colours.txt

printf() 函数

为了让输出结果时格式更灵活,你可以使用 awkprintf() 函数。 它与 C、Lua、Bash 和其他语言中的 printf 相类似。它也接受以逗号分隔的格式参数。参数列表需要写在括号里。

$ printf 格式, 项目1, 项目2, ...

格式这一参数(也叫格式符)定义了其他参数如何显示。这一功能是用格式修饰符实现的。%s 输出字符,%d 输出十进制数字。下面的 printf 语句,会在括号内显示字段数量:

$ awk 'printf "%s (%d)\n",$0,NF}' colours.txt
name       color  amount (3)
raspberry  red    4 (3)
banana     yellow 6 (3)
[...]

在这个例子里,%s (%d) 确定了每一行的输出格式,$0,NF 定义了插入 %s%d 位置的数据。注意,和 print 函数不同,在没有明确指令时,输出不会转到下一行。出现转义字符 \n 时才会换行。

Awk 脚本编程

这篇文章中出现的所有 awk 代码,都在 Bash 终端中执行过。面对更复杂的程序,将命令放在文件(脚本)中会更容易。-f FILE 选项(不要和 -F 弄混了,那个选项用于字段分隔符),可用于指明包含可执行程序的文件。

举个例子,下面是一个简单的 awk 脚本。创建一个名为 example1.awk 的文件,包含以下内容:

/^a/ {print "A: " $0}
/^b/ {print "B: " $0}

如果一个文件包含 awk 程序,那么在给文件命名时,最好写上 .awk 的扩展名。 这样命名不是强制的,但这么做,会给文件管理器、编辑器(和你)一个关于文件内容的很有用的提示。

执行这一脚本:

$ awk -f example1.awk colours.txt
A: raspberry  red    4
B: banana     yellow 6
A: apple      green  8

一个包含 awk 命令的文件,在最开头一行加上释伴 #!,就能变成可执行脚本。创建一个名为 example2.awk 的文件,包含以下内容:

#!/usr/bin/awk -f
#
# 除了第一行,在其他行前显示行号
#

NR > 1 {
    printf "%d: %s\n",NR,$0
}

可以说,脚本中只有一行,大多数情况下没什么用。但在某些情况下,执行一个脚本,比记住,然后打一条命令要容易的多。一个脚本文件,也提供了一个记录命令具体作用的好机会。以 # 号开头的行是注释,awk 会忽略它们。

给文件可执行权限:

$ chmod u+x example2.awk

执行脚本:

$ ./example2.awk colours.txt
2: apple      red    4
2: banana     yellow 6
4: raspberry red    3
5: grape      purple 10
[...]

awk 命令放在脚本文件中,有一个好处就是,修改和格式化输出会更容易。在终端中,如果能用一行执行多条 awk 命令,那么输入多行,才能达到同样效果,就显得有些多余了。

试一试

你现在已经足够了解,awk 是如何执行指令的了。现在你应该能编写复杂的 awk 程序了。试着编写一个 awk 脚本,它需要: 至少包括一个条件模式,以及多个规则。如果你想使用除 printprintf 以外的函数,可以参考在线 gawk 手册

下面这个例子是个很好的切入点:

#!/usr/bin/awk -f
#
#  显示所有记录 除了出现以下情况
#  如果第一个记录 包含 “raspberry”
#  将 “red” 替换成 “pi”

$1 == "raspberry" {
        gsub(/red/,"pi")
}

{ print }

试着执行这个脚本,看看输出是什么。接下来就看你自己的了。

这一系列的下一篇文章,将会介绍更多,能在更复杂(更有用!) 脚本中使用的函数。

这篇文章改编自 Hacker Public Radio 系列,一个技术社区博客。


via: https://opensource.com/article/19/11/fields-records-variables-awk

作者:Seth Kenlon 选题:lujun9972 译者:wenwensnow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出