mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
commit
1e0a935374
@ -0,0 +1,84 @@
|
||||
[#]: subject: "Here’s Why Firefox is Seeing a Continuous Decline for Last 12 Years"
|
||||
[#]: via: "https://news.itsfoss.com/firefox-continuous-decline/"
|
||||
[#]: author: "Community https://news.itsfoss.com/author/team/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "wxy"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13780-1.html"
|
||||
|
||||
Firefox 在过去 12 年里损失了 5 亿用户及其 75% 份额的原因
|
||||
======
|
||||
|
||||
> 一位有四十年编程经验的老程序员表达了他对 Firefox 浏览器为何逐渐衰退的看法。
|
||||
|
||||
![](https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/09/decline.png?w=1200&ssl=1)
|
||||
|
||||
最近有很多关于 Firefox 浏览器衰落的讨论,还有很多讨论 [它在过去两年里失去了 5000 万用户][1] 的文章。
|
||||
|
||||
但是 **实际上它的衰落已经有 12 年之久了,总共损失了 5 亿用户和它曾经拥有的市场份额的 75%**。
|
||||
|
||||
这一切都开始于 2009 年第三季度,其致命的决定是强迫……
|
||||
|
||||
### 顶部标签
|
||||
|
||||
自从 [做了这个决定][2],Firefox 就开始丢失市场份额。PC 上的所有程序都使用针对活动窗口的标签。如微软 Office 和 Adobe 这样的专有软件,如 GIMP、3D 设计、视频编辑器、十六进制编辑器这样的 FOSS 软件,你能想的的种种软件都是这样的,这是标准的、合乎逻辑的设计。
|
||||
|
||||
然后,谷歌决定将标签放在其 Chrome 浏览器的顶部,该浏览器是为移动设备而非台式机设计的。在智能手机上,这可能是有意义的,因为没有空间来容纳一个完整的桌面风格的菜单布局。但在桌面上,它是反直觉的,并且会破坏与所有其他程序的工作流程。台式机的代码与手机不同,所以没有合理的理由试图将移动用户界面强加给台式机用户,而台式机是 Firefox 的主要用户群。在一个 400 万行的代码库中,由两行代码所制定的单一设置“太难维护”的论点,只是在侮辱用户的智商。代码不是草坪,如果你几周不管它,它也不会改变。
|
||||
|
||||
当用户对这一变化的投诉蜂拥而至时,我从一位不愿透露姓名的主要开发者那里得到的回应是:“我们有数亿用户。5000 人的抱怨并不代表大多数的用户。”这些投诉有一个共同的观点:“如果我想让我的浏览器看起来像 Chrome,我就会使用 Chrome。”于是他们就这么做了。
|
||||
|
||||
### 不断删除“没人使用”的功能
|
||||
|
||||
对 Firefox 所做的每项改动都是一样的做法。默认功能被改变了,但有一个菜单设置可以恢复它。然后菜单设置被删除,你只能通过`about:config` 来改变它。再然后,`about:config` 选项也被删除了。用户群的每一次抗议都得到了同样的回应:“你只是极少数人,大多数人喜欢这种改变。”
|
||||
|
||||
75% 并不是少数人。几乎每个人都讨厌这些变化,每一次变化都会把更多的用户赶走,而 Mozilla 工作人员傲慢的、居高临下的回应让用户们有苦难言,让他们再也不想回来了。仔细观察,你可以看到每次删除一些功能,用户数量都有明显的下降,只有在第三方组件或 CSS 恢复了这些变化时才会稳定下来。一次又一次,年复一年。他们没有学到任何教训。
|
||||
|
||||
光是移除设置还不够。Firefox 继续阉割附加组件和主题,强迫集中签名,并最终废除了 XUL,而没有足够的 Web 扩展 API 来替代失去的功能。在抱怨这一变化时,我再次与一位主要开发者(同一个人)交谈。他的回答是(原话)“人们并不是因为附加组件而使用 Firefox 的。我们的遥测显示 80% 的用户从未安装过任何附加组件。”也就是说,任何懂技术的人都会立即关闭遥测,因为他们不想让浏览器监视他们,对此我们也曾无数次抱怨过。
|
||||
|
||||
即使是他们在用户界面设计方面的一项重大举措,即可拖放定制的 Australis 界面,也因为可怕的默认布局和缺乏不需要 CSS 的选项而疏远了更多用户。难看的斜角标签(抄袭自 Chrome)是 Mozilla 唯一承认糟糕的用户界面变化,而且令人惊讶的是,他们只是在 Chrome 取消了斜角标签 **之后** 才这样做。
|
||||
|
||||
时至今日,Mozilla 仍然声称要听取用户的意见,但 12 年后,他们仍然无视我们,难看的默认 Proton 用户界面是最新强加给不情愿的用户群的愚蠢选择。(如果你认为我属于少数的话,可以在谷歌上输入 “Firefox Proton” 来查看最常搜索的建议。)幸运的是,它仍然可以用 `userChrome.css` 来大致修复,但即使是我,也已经厌倦了必须反复修补新的代码来跟上不断的弃用和格式变化。
|
||||
|
||||
### 糟糕的编码范式
|
||||
|
||||
Mozilla 的源代码是一场噩梦。例如,默认配置文件的位置被定义了 3 次,使用了 3 种不同的语言的不同的变量,其中之一是由位于不同文件中的多个变量组合生成的。我看到的另外一个例子是在 6 个不同的文件中定义的另一个全局变量。
|
||||
|
||||
在编译后,下载历史、访问过的网页、书签等等,都被一起塞进了乱七八糟的文件中。最终的结果是什么?试着从你的历史记录中删除 400 个条目,看看它需要多长时间。而从一个单独的文本文件中删除这么多行,只需要一瞬间。想改变一个图标的外观或为自定义搜索添加一个新的图标?它们大多只是 PNG,但它们被混淆并被封入 `omni.ja` 文件。本来可以用你选择的编辑器在几秒钟内改变,但你需要安装和学习 Eclipse 之类的程序,并在每次更改时重新编译文件。这样的例子不胜枚举。
|
||||
|
||||
难怪 Mozilla 的码农在寻找和修复错误方面这么困难。这导致了更糟糕的编码范式,为了修复错误而记录一切。它部分导致了...
|
||||
|
||||
### 糟糕的内存管理
|
||||
|
||||
如果一个程序坐在那里什么都不做,它的内存使用量不应该改变。看看我的内存管理器,我有 40 个进程在遵守这个原则。尽管什么都不做,却不断地读写磁盘的唯一程序是什么?Firefox。它正在运行 13 个进程,所有这些进程都在不断地做这两件事。我写了 40 年的代码,造了 30 年的电脑,所以我确实了解一点计算机如何工作的事情。这就是基础层面上的糟糕设计,在表面上做再多的修补也无济于事。
|
||||
|
||||
代码范式是 Mozilla 性能问题的根源,他们不会解决这个问题。我敢打赌,这也是 FirefoxOS 失败的原因,它是一个伟大的想法,但由于执行不力和编码实践问题,导致太多的错误无法修复而失败。
|
||||
### 在告诉我们“我们重视你的隐私”的同时,侵犯了你的隐私
|
||||
|
||||
就是遥测。当你点击“禁用遥测”时,隐藏的遥测并没有被禁用。首次运行也要发出遥测信号。强制签署附加组件。无法关闭的自动更新,每 10 分钟发出一次信号。需要单独选择退出的“实验”。现在最新的问题是,只是为了制作一个自定义的主题,就强制使用基于 2FA 的应用以登录到 Firefox 插件帐户,如果不是强制签署附加组件,根本就不需要。
|
||||
|
||||
Mozilla 对用户隐私的尊重和对我们意见的尊重一样少。
|
||||
|
||||
### 总结
|
||||
|
||||
事情不一定是这样的。虽然还没有,但是不能承认自己的错误,也不考虑不同的意见的人,注定要停滞不前,走向衰败。Mozilla 的决策者似乎就是这样想的,所以我对未来不抱什么希望。希望你们中的一些人至少能从他们的错误中学习,在他们失败的地方取得成功。通过为用户提供他们想要的东西,而不是告诉他们应该想要什么来取得成功。通过提供市场上缺少的东西,而不是盲目地试图复制你的竞争对手。
|
||||
|
||||
*本文所表达的观点和意见仅代表作者本人,不一定反映本站和 It's FOSS 的官方政策或立场。*
|
||||
|
||||
> 作者信息:Dan 来自澳大利亚墨尔本,已经有大约 40 年的编码经验,做了 25 年的平面设计。他还从事基于 3D 打印机套件的开源机械设计。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/firefox-continuous-decline/
|
||||
|
||||
作者:[Community][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/team/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://news.itsfoss.com/firefox-decline/
|
||||
[2]: https://www.wired.com/2009/07/mozilla-considers-copying-chrome-for-firefox-4dot0/
|
@ -1,81 +0,0 @@
|
||||
[#]: subject: "Adobe Kills Brackets Code Editor & Suggests Using Visual Studio Code"
|
||||
[#]: via: "https://news.itsfoss.com/adobe-kills-brackets-editor/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Adobe Kills Brackets Code Editor & Suggests Using Visual Studio Code
|
||||
======
|
||||
|
||||
Brackets was an impressive open-source modern code editor available for Windows, macOS, and Linux.
|
||||
|
||||
Adobe created it as a community-guided project to help web developers. We previously listed it as one of the [best modern text editors available for coders][1].
|
||||
|
||||
Unfortunately, Adobe ended its support for Brackets on September 1, 2021.
|
||||
|
||||
### Why Did Adobe Discontinue Brackets?
|
||||
|
||||
![][2]
|
||||
|
||||
It looks like Adobe’s partnership with Microsoft may have encouraged them to pull the plug off the community project.
|
||||
|
||||
Hence, they recommend users migrate to Microsoft’s Visual Studio Code editor.
|
||||
|
||||
![][3]
|
||||
|
||||
This is what Brackets’ original GitHub page says after the discontinuation of the project.
|
||||
|
||||
### Visual Studio Code as a Replacement to Brackets
|
||||
|
||||
Of course, Microsoft’s Visual Studio Code is a fantastic alternative and built on open-source. However, when you download the Visual Studio Code from their website, it does not come under a license that promotes free and open-source software.
|
||||
|
||||
So, you may have to build from source or try [VSCodium][4], a freely licensed edition of Visual Studio Code minus the telemetry/tracking.
|
||||
|
||||
Also, there is an [official guide on migrating from Brackets][5] that you can explore if interested.
|
||||
|
||||
### Brackets Will Continue as a Fork Without Adobe
|
||||
|
||||
![][6]
|
||||
|
||||
Even though Adobe has discontinued the project, the [original website][7] still exists to maintain a fork of the project.
|
||||
|
||||
The project’s name is subject to change, but as of now, it’s “**Brackets Continued**” to help users identify the fork.
|
||||
|
||||
Do note that the fork does not yet have a release, and we have no idea if it will continue as an independent project.
|
||||
|
||||
So, if you want to help Brackets fork and help maintain it somehow, head to its GitHub page for more details.
|
||||
|
||||
[Brackets Continued (Fork)][8]
|
||||
|
||||
_What do you prefer to use as your code editor? Did you like Brackets code editor for web development work? Feel free to share your thoughts on this in the comments._
|
||||
|
||||
#### Big Tech Websites Get Millions in Revenue, It's FOSS Got You!
|
||||
|
||||
If you like what we do here at It's FOSS, please consider making a donation to support our independent publication. Your support will help us keep publishing content focusing on desktop Linux and open source software.
|
||||
|
||||
I'm not interested
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/adobe-kills-brackets-editor/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
|
||||
[2]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ3MCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[3]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE1NCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[4]: https://vscodium.com
|
||||
[5]: https://code.visualstudio.com/migrate-from-brackets
|
||||
[6]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjMyNyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[7]: https://brackets.io
|
||||
[8]: https://github.com/brackets-cont/brackets
|
@ -1,87 +0,0 @@
|
||||
[#]: subject: "Here’s Why Firefox is Seeing a Continuous Decline for Last 12 Years"
|
||||
[#]: via: "https://news.itsfoss.com/firefox-continuous-decline/"
|
||||
[#]: author: "Community https://news.itsfoss.com/author/team/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Here’s Why Firefox is Seeing a Continuous Decline for Last 12 Years
|
||||
======
|
||||
|
||||
There has been a lot of discussion lately about the decline of the Firefox browser and numerous articles about it [losing 50 Million users in the last two years][1].
|
||||
|
||||
But the _**real decline has been over 12 years with a total loss of half a Billion users**_ and 75% of the market share it once held.
|
||||
|
||||
It all started in 2009 Q3 with the fateful decision to force…
|
||||
|
||||
### Tabs-On-Top
|
||||
|
||||
As soon as [this decision was made][2], Firefox starting losing market share. Every other program on a PC uses tabs against the active window. Proprietary software like MS Office and Adobe, FOSS software like Notepad++ and GIMP, 3D design, video editors, hex editors, you name it: It is the standard, logical design.
|
||||
|
||||
Then Google decided to make the tabs on top standard for its Chrome browser, which was designed for mobile devices not desktops. On a smartphone it may make sense, as there isn’t room for a full desktop style menu layout. On a desktop it is counterintuitive and breaks workflow with all other programs. The code for desktops is different from phones so there was no rational reason to try and force a mobile UI onto desktop users who were Firefox’s primary userbase. The argument that it was “too hard to maintain” a single setting enacted by 2 lines of code in a 4 Million line codebase is just insulting to the intelligence of users. Code isn’t a lawn. It doesn’t change if you leave it alone for a few weeks.
|
||||
|
||||
When inundated with user complaints about the change, the response I received from a lead developer who shall remain nameless was “We have hundreds of millions of users. 5000 people complaining doesn’t represent the majority of users”. Those complaints had one common sentiment, “If I wanted my browser to look like Chrome I’d just use Chrome”. And so they did.
|
||||
|
||||
### Constant removal of features “that no-one uses”
|
||||
|
||||
Every change made to Firefox had the same pattern. The default feature was changed, but there was a menu setting to revert it. Then the menu setting was removed and you could only change it via about:config. Then the about:config option was removed. Every protest from the userbase met the same response “You’re just a tiny minority, most people like the change”.
|
||||
|
||||
75% is not a minority. Almost everyone hated the changes and each change pushed more users away, and the arrogant, condescending responses from Mozilla staff left a bitter taste in their mouth ensuring they would never return. Looking closely at the user numbers you could see a visible drop with every removal, only stabilising when a third party add-on or CSS would revert the change. Over and over, year after year. No lessons were learnt.
|
||||
|
||||
Removing settings wasn’t enough. Firefox went on to neuter add-ons and themes, forcing centralised signing and ultimately deprecating XUL without adequate webextension api’s to replace lost functionality. Complaining about this change I again spoke to one of the lead developers (same guy). His response was (exact quote) “People don’t use Firefox because of add-ons. Our telemetry shows 80% of users never install any add-ons” i.e. the telemetry that any tech savvy person immediately turns off because they don’t want their browser spying on them and about which we have also complained numerous times.
|
||||
|
||||
Even the one great move they made in UI design, the drag and drop customisable Australis interface, alienated more users because of the horrible default layout and lack of options that didn’t need CSS. The awful angled tabs (copied from chrome) is the only UI change Mozilla has admitted was terrible and they only did so, surprise surpise, AFTER chrome did away with them.
|
||||
|
||||
To this day, Mozilla still claims to want to hear from their users and after 12 years they still keep ignoring us, the awful default Proton UI being the latest foolish choice forced upon an unwilling userbase. (Type in “Firefox Proton” on Google to look at the most commonly searched suggestions if you think I’m in the minority). Fortunately it can still be mostly fixed with userChrome.css but even I’m getting sick of having to repeatedly patch together new code to keep up with constant deprecation and format changes.
|
||||
|
||||
### Bad coding paradigms
|
||||
|
||||
Mozilla’s source code is a nightmare. For example, default profile location is defined 3 times, using different variables, in 3 different languages, one of which is generated by combining multiple variables located in separate files. Another example I saw was another global variable being defined in 6 different files.
|
||||
|
||||
Post compiling, history for downloads, visited pages, bookmarks etc, are all shoved together into obfuscated files. The end result? Try deleting 400 entries from your history and watch how long it takes. Deleting that many lines from a separate text file would take a split second. Want to change the appearance of an icon or add a new one for a custom search? They’re mostly just PNGs, but they are obfuscated and sealed into the omni.ja file. Could otherwise be changed in seconds with your editor of choice, instead you need to install and learn a program like Eclipse and recompile the file with every change. The list goes on and on.
|
||||
|
||||
It is no wonder Mozilla’s coders have such trouble finding and fixing bugs. This led to an even worse coding paradigm, logging everything for the purpose of bugfixes. This is one of the culprits of…
|
||||
|
||||
### Poor memory management
|
||||
|
||||
If a program is sitting there doing nothing, its memory usage should not change. Looking at my memory manager I have 40 processes obeying this principle. What is the only program constantly reading and writing to disk despite doing nothing? Firefox. It is running 13 processes and all of them are constantly doing both. I’ve been coding for 40 years and building PC’s for 30 so I do know a thing or two about how computing works. This is just awful design at the base level and no amount of tinkering on the surface will fix that.
|
||||
|
||||
The code paradigm is the root of Mozilla’s performance issues and they won’t address it. I’ll wager that’s also the reason for the failure of FirefoxOS, which was a great idea but failed because of poor execution and coding practices resulting in too many bugs to fix.
|
||||
|
||||
### Invading your privacy at the same time as telling us “we value your privacy”
|
||||
|
||||
Telemetry. Hidden telemetry that isn’t disabled when you click “disable telemetry”. Firstrun pings. Forced signing of add-ons. Auto-updates you can’t switch off, pinging every 10 minutes. “Experiments” which require a separate opt out. Now the latest offence is enforcing app based 2FA to login to a Firefox Add-on account just to make a custom theme, which you wouldn’t need in the first place if not for forced add-on signing.
|
||||
|
||||
Mozilla has as little respect for their users privacy as they do for our opinions.
|
||||
|
||||
### Final thoughts
|
||||
|
||||
It didn’t have to be this way. It still doesn’t, but the mind that is incapable of admitting when it is wrong, or of considering differing opinions is doomed to stagnation and decay. The decision makers of Mozilla appear to have such minds so I do not hold out much hope for the future. Hopefully some of you out there can at least learn from their mistakes and succeed where they are failing. You succeed by giving users what they want, not telling them what they should want. By providing what is missing in the market, not blindly trying to copy your competitors.
|
||||
|
||||
_The views and opinions expressed are those of the authors and do not necessarily reflect the official policy or position of It’s FOSS._
|
||||
|
||||
Author info: From Melbourne Australia, Dan has been coding for about 40 years and doing graphic design for 25 years. He also works on open source mechanical designs based on 3D printer kits.
|
||||
|
||||
#### Big Tech Websites Get Millions in Revenue, It's FOSS Got You!
|
||||
|
||||
If you like what we do here at It's FOSS, please consider making a donation to support our independent publication. Your support will help us keep publishing content focusing on desktop Linux and open source software.
|
||||
|
||||
I'm not interested
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/firefox-continuous-decline/
|
||||
|
||||
作者:[Community][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/team/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://news.itsfoss.com/firefox-decline/
|
||||
[2]: https://www.wired.com/2009/07/mozilla-considers-copying-chrome-for-firefox-4dot0/
|
@ -0,0 +1,103 @@
|
||||
[#]: subject: "Fedora 35 Release Date and Expected New Features"
|
||||
[#]: via: "https://news.itsfoss.com/fedora-35-release-date-features/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Fedora 35 Release Date and Expected New Features
|
||||
======
|
||||
|
||||
Fedora 35 is just around the corner. And, if you cannot wait already, let us highlight some of the essential details about the release.
|
||||
|
||||
### Fedora 35 Release Date
|
||||
|
||||
The expected release date for Fedora 35 beta is **14th September 2021**. But, if delayed, the next planned date is **21st September 2021**.
|
||||
|
||||
After the public beta testing, the final release has been planned for **19th October 2021,** with a delayed date for **26th October 2021.**
|
||||
|
||||
Of course, you can get your hands on Fedora 35 before the final and beta releases as well. But, considering it is just a few days away from its first beta release, you may want to wait it out.
|
||||
|
||||
### Fedora 35 Features
|
||||
|
||||
![][1]
|
||||
|
||||
[Fedora 34][2] was an exciting release with GNOME 40 and a new i3 spin. And Fedora 35 is also shaping up as an interesting upgrade to it.
|
||||
|
||||
Some of the fundamental changes that you can expect are:
|
||||
|
||||
#### GNOME 41
|
||||
|
||||
GNOME 41 may not be a radical change when compared to [GNOME 40][3], but there are some visual improvements and valuable feature additions that you can expect.
|
||||
|
||||
For instance, the GNOME Software will get a clean look and context tiles, resembling much like all the details that you can find in the [Apps for GNOME][4] portal. You should also find [VoIP support added to GNOME 41][5].
|
||||
|
||||
A new “**Connections**” app has been added to let you connect to other platforms/systems remotely.
|
||||
|
||||
GNOME 41 has a planned release date of **September 22, 2021**. So, you may want to watch out for our coverage for the complete details when it releases.
|
||||
|
||||
#### DNS Over TLS Support
|
||||
|
||||
DNS Over TLS (DoT) is essential to encrypt DNS requests and prevent your ISP from spying. With Fedora 35, any configured DNS server should automatically attempt to connect using DoT if the DNS supports it.
|
||||
|
||||
#### Default Btrfs Filesystem for Fedora Cloud
|
||||
|
||||
While Fedora has already switched to the Btrfs filesystem since [Fedora 33][6], they enforce that change for the Cloud edition.
|
||||
|
||||
#### Linux Kernel 5.14
|
||||
|
||||
[Linux Kernel 5.14][7] wasn’t a big release, but it added many features, especially when it comes to ARM devices.
|
||||
|
||||
For Fedora 35, the improved hardware support should make a difference.
|
||||
|
||||
#### Flathub Applications Included with Third-Party Repositories
|
||||
|
||||
You also get some selected Flatpak applications added from a filtered Flathub remote when you enable third-party repositories.
|
||||
|
||||
This should come in handy for better third-party app support in Fedora.
|
||||
|
||||
#### PulseAudio Daemon Replaced by PipeWire
|
||||
|
||||
While we saw initial implementations of replacing PulseAudio in Fedora 34, this time, there is a proposal to replace the PulseAudio daemon with a compatible implementation based on PipeWire.
|
||||
|
||||
### Other Improvements
|
||||
|
||||
Along with the key highlights mentioned above, you should find several under-the-hood changes and package updates that could translate as significant upgrades.
|
||||
|
||||
For instance, the Firewalld package update and the GNU Toolchain update should prove to be valuable upgrades.
|
||||
|
||||
You can explore more about the proposed changes in their [official changeset wiki][8].
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
It should be exciting to see the changes in the final release. For now, let us keep an eye out to test the public beta release. And, if you do not want to experiment on your system with a beta release, you should wait for the stable release.
|
||||
|
||||
#### Big Tech Websites Get Millions in Revenue, It's FOSS Got You!
|
||||
|
||||
If you like what we do here at It's FOSS, please consider making a donation to support our independent publication. Your support will help us keep publishing content focusing on desktop Linux and open source software.
|
||||
|
||||
I'm not interested
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/fedora-35-release-date-features/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUyMSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[2]: https://news.itsfoss.com/fedora-34-release/
|
||||
[3]: https://news.itsfoss.com/gnome-40-release/
|
||||
[4]: https://news.itsfoss.com/apps-for-gnome-portal/
|
||||
[5]: https://news.itsfoss.com/gnome-41-beta/
|
||||
[6]: https://itsfoss.com/fedora-33/
|
||||
[7]: https://news.itsfoss.com/kernel-5-14-release/
|
||||
[8]: https://fedoraproject.org/wiki/Releases/35/ChangeSet
|
@ -0,0 +1,45 @@
|
||||
[#]: subject: "What I miss about open source conferences"
|
||||
[#]: via: "https://opensource.com/article/21/9/why-i-miss-conferences"
|
||||
[#]: author: "Mike Bursell https://opensource.com/users/mikecamel"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
What I miss about open source conferences
|
||||
======
|
||||
I can buy my own t-shirts, but friendships need nurturing.
|
||||
![Stickers from all different open source projects and communities][1]
|
||||
|
||||
A typical work year would involve my attending maybe six to eight conferences in person and speaking at quite a few of them. A few years ago, I stopped raiding random booths at the exhibitions usually associated with these for t-shirts for the simple reason that I had too many of them. That's not to say that I wouldn't accept one here or there if it was particularly nice, or an open source project which I esteemed particularly, for instance. Or ones which I thought my kids would like—they're not "cool" but are at least useful for sleepwear, apparently. I also picked up a lot of pens and enough notebooks to keep me going for a while.
|
||||
|
||||
And then, at the beginning of 2020, the pandemic hit, I left San Francisco, where I'd been attending meetings co-located with RSA North America (my employer at the time made the somewhat prescient decision not to allow us to go to the main conference), and I've not attended any in-person conferences since.
|
||||
|
||||
There are some good things about this, the most obvious being less travel, though, of late, my family has been dropping an increasing number of not-so-subtle hints about how it would be good if I let them alone for a few days so they can eat food I don't like (pizza and macaroni cheese, mainly) and watch films that I don't enjoy (largely, but not exclusively, romcoms on Disney+). The downsides are manifold. Having to buy my own t-shirts and notebooks, obviously, though it turns out that I'd squirreled away enough pens for the duration. It also turned out that the move to USB-C connectors hadn't sufficiently hit the conference swag industry by the end of 2019 for me to have enough of those to keep me going, so I've had to purchase some of those. That's the silly, minor stuff, though—what about areas where there's real impact?
|
||||
|
||||
Virtual conferences aren't honestly too bad, and the technology has definitely improved over the past few months. I've attended some very good sessions online (and given my share of sessions and panels, whose quality I won't presume to judge), but I've realised that I'm much more likely to attend borderline-interesting talks not on my main list of "must-sees" (some of which turn out to be very valuable) if I've actually traveled to get to a venue. The same goes for attention. I'm much less likely to be checking email, writing emails, and responding to chat messages in an in-person conference than a virtual one. It's partly about the venue, moving between rooms, and not bothering to get my laptop out all the time—not to mention the politeness factor of giving your attention to the speaker(s) or panellists. When I'm sitting at my desk at home, none of these is relevant, and the pull of the laptop (which is open anyway to watch the session) is generally irresistible.
|
||||
|
||||
Two areas that have really suffered, though, are the booth experience and the "hallway track." I've had some very fruitful conversations, both from dropping by booths (sometimes mainly for a t-shirt—see above) or from staffing a booth and meeting those who visit. I've yet to attend any virtual conferences where the booth experience has worked, particularly for small projects and organisations. Online chat isn't the same, and the serendipitous aspect of wandering past a booth and seeing something you'd like to talk about is pretty much entirely missing if you have to navigate a set of webpages of menu options with actual intent.
|
||||
|
||||
The hallway track is meeting people outside a conference's main sessions, either people you know already or as conversations spill out of sessions you've been attending. Knots of people asking questions of presenters or panellists can reveal shared interests, opposing but thought-provoking points of view, or just similar approaches to a topic which can lead to valuable professional relationships and even long-term friendships. I'm not a particularly gregarious person—particularly if I'm tired and jetlagged—but I really enjoy catching up with colleagues and friends over a drink or a meal from time to time. While that's often difficult given the distributed nature of the companies and industries I've been involved with, conferences have presented great opportunities to meet up, have a chinwag and discuss the latest tech trends, mergers and acquisitions, and fashion failures of our fellow attendees. This is what I miss most: I can buy my own t-shirts, but friendships need nurturing. And I hope that we can safely start attending conferences again so that I can meet up with friends and share a drink. I just hope I'm not the one making the fashion mistakes (this time).
|
||||
|
||||
* * *
|
||||
|
||||
_This article was originally published on [Alice, Eve, and Bob][2] and is reprinted with the author's permission._
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/9/why-i-miss-conferences
|
||||
|
||||
作者:[Mike Bursell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mikecamel
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/stickers-osdc-lead.png?itok=2RNn132b (Stickers from all different open source projects and communities)
|
||||
[2]: https://aliceevebob.com/2021/08/24/buying-my-own-t-shirts-or-what-i-miss-about-conferences/
|
@ -1,116 +0,0 @@
|
||||
[#]: subject: "How to Run Java Programs in Ubuntu"
|
||||
[#]: via: "https://itsfoss.com/run-java-program-ubuntu/"
|
||||
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How to Run Java Programs in Ubuntu
|
||||
======
|
||||
|
||||
So, you have started learning Java programming? That’s good.
|
||||
|
||||
And you want to run the java programs on your Linux system? Even better.
|
||||
|
||||
Let me show how to run Java in terminal in Ubuntu and other Linux distributions.
|
||||
|
||||
### Running Java programs in Ubuntu
|
||||
|
||||
Let’s go in proper steps here.
|
||||
|
||||
#### Step 1: Install Java compiler
|
||||
|
||||
To run a Java program, you need to compile the program first. You need Java compiler for this purpose.
|
||||
|
||||
The Java compiler is part of [JDK][1] (Java Development Kit). You need to install JDK in order to compile and run Java programs.
|
||||
|
||||
First, check if you already have Java Compiler installed on your system:
|
||||
|
||||
```
|
||||
javac --version
|
||||
```
|
||||
|
||||
If you see an error like “Command ‘javac’ not found, but can be installed with”, this means you need to install Java Development Kit.
|
||||
|
||||
![Check if Java compiler is already installed or not][2]
|
||||
|
||||
The simplest way to install JDK on Ubuntu is to go with the default offering from Ubuntu:
|
||||
|
||||
```
|
||||
sudo apt install default-jdk
|
||||
```
|
||||
|
||||
You’ll be asked to enter your account’s password. When you type the password, nothing is seen on the screen. That is normal. Just enter your password blindly. When asked, press the enter key or Y key.
|
||||
|
||||
![Installing JDK that also contains the Java compiler][3]
|
||||
|
||||
The above command should work for other Debian and Ubuntu based distributions like Linux Mint, elementary OS etc. For other distributions, use your distribution’s package manager. The package name could also be different.
|
||||
|
||||
Once installed, verify that javac is available now.
|
||||
|
||||
![Verify that Java compiler can be used now][4]
|
||||
|
||||
#### Step 2: Compile Java program in Linux
|
||||
|
||||
You need to have a Java program file for this reason. Let’s say you create a new Java program file named **HelloWorld.java** and it has the following content:
|
||||
|
||||
```
|
||||
class HelloWorld{
|
||||
public static void main(String args[]){
|
||||
System.out.println("Hello World");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can [use Nano editor in terminal][5] or Gedit graphical text editor for writing your Java programs.
|
||||
|
||||
```
|
||||
javac HelloWorld.java
|
||||
```
|
||||
|
||||
If there is no error, the above command produces no output.
|
||||
|
||||
When you compile the Java program, it generates a .class file with the class name you used in your program. You have to run this class file.
|
||||
|
||||
#### Step 3: Run the Java class file
|
||||
|
||||
You do not need to specify the class extension here. Just the name of the class. And this time, you use the command java, not javac.
|
||||
|
||||
```
|
||||
java HelloWorld
|
||||
```
|
||||
|
||||
This will print Hello World on the screen for my program.
|
||||
|
||||
![Running java programs in the Linux terminal][6]
|
||||
|
||||
And that’s how you run a Java program in the Linux terminal.
|
||||
|
||||
This was the simplest of the example. The sample program had just one class. The Java compiler creates a class file for each class in your program. Things get complicated for bigger programs and projects.
|
||||
|
||||
This is why I advise [installing Eclipse on Ubuntu][7] for proper Java programming. It is easier to program in an IDE.
|
||||
|
||||
I hope you find this tutorial helpful. Questions or suggestions? The comment section is all yours.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/run-java-program-ubuntu/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://jdk.java.net/
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/java-compiler-check-ubuntu.png?resize=800%2C328&ssl=1
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/09/install-jdk-ubuntu.png?resize=800%2C430&ssl=1
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/java-compiler-ubuntu.png?resize=798%2C226&ssl=1
|
||||
[5]: https://itsfoss.com/nano-editor-guide/
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/running-java-programs-in-Linux-terminal.png?resize=798%2C301&ssl=1
|
||||
[7]: https://itsfoss.com/install-latest-eclipse-ubuntu/
|
@ -1,127 +0,0 @@
|
||||
[#]: subject: "How to Use the dd Command to Create a Live USB Drive in Linux Terminal [For Experts and Adventurers]"
|
||||
[#]: via: "https://itsfoss.com/live-usb-with-dd-command/"
|
||||
[#]: author: "Hunter Wittenborn https://itsfoss.com/author/hunter/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "perfiffer"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How to Use the dd Command to Create a Live USB Drive in Linux Terminal [For Experts and Adventurers]
|
||||
======
|
||||
|
||||
There are several graphical tools available for creating live USB. [Etcher on Linux][1] is probably the most popular. Ubuntu has its own Startup Disk Creator tool for this purpose.
|
||||
|
||||
However, advanced Linux users swear by the comfort and swiftness of creating live USBs in Linux terminal using the dd command.
|
||||
|
||||
The dd command is a [CLI tool][2] that gives you powerful features for copying and converting files.
|
||||
|
||||
A common use case that people use dd for is to write ISO files to an external storage device such as a USB drive, which can be used to do things like install a new Linux distribution onto a computer or laptop.
|
||||
|
||||
That’s what I am going to show in this tutorial. I’ll go over the commands you will need to run, finding our USB drive from the terminal, and then finally doing the actual flashing of the ISO file.
|
||||
|
||||
### Creating live USB from ISO with dd command
|
||||
|
||||
Before I show you the steps, let me quickly go over the command which you’ll be using and explain what it does.
|
||||
|
||||
Here’s the example command for flashing of the ISO:
|
||||
|
||||
```
|
||||
dd if="./filename.iso" of="/dev/sdb" status="progress" conv="fsync"
|
||||
```
|
||||
|
||||
Let’s go over what exactly that [dd command][3] is doing.
|
||||
|
||||
#### Understanding the above dd command
|
||||
|
||||
![Explanation of the dd command for live USB creation][4]
|
||||
|
||||
First, you enter `dd`. As expected, this is just the name of the program you are going to run.
|
||||
|
||||
Next, you specify `if="./filename.iso"`. `if` stands for input file, which tells `dd` what file you are going to be writing to the external storage drive.
|
||||
|
||||
After that, you enter `of="/dev/sdb"`. As was with `if`, `of` simply stands for output file.
|
||||
|
||||
The thing to remember is that the output file doesn’t technically have to be a file on your system. You can also specify things like the path to an external device (as shown in the example), which just **looks** like a normal file on your system, but actually points to a device connected to your machine.
|
||||
|
||||
`status` can be set to three options: `none`, `noxfer` and `progress.`
|
||||
|
||||
The `progress` option that you set will cause dd to show periodic statistics on how much of the ISO has been transferred to the storage drive, as well as an estimation on how much longer it will be until dd is finished.
|
||||
|
||||
If you were to have set the `none` option instead, dd would only print error messages during the writing of the ISO, thus removing things like the progress bar.
|
||||
|
||||
The `noxfer` option hides some information that’s printed after a transfer is complete, such as how long it took from start to finish.
|
||||
|
||||
Lastly, you set the `conv` option to `fsync`. This causes dd to not report a successful write until the entire ISO has been written to the USB drive.
|
||||
|
||||
If you omit this option, dd will still write just fine (and might actually appear to run quicker), but you might find your system taking quite a while before it tells you it’s safe to remove the USB drive as it will finish writing the ISO’s content in the background, thus allowing you to do other things in the meantime.
|
||||
|
||||
_**Now that you understand what you have to do, let’s see how to do it.**_
|
||||
|
||||
Warning
|
||||
|
||||
The command line is a double-edged sword. Be extra careful when you are running a command like dd. You must make sure that you are using the correct device for the output file destination. One wrong step and you may format your main system disk and lose your operating system.
|
||||
|
||||
#### Step 0: Download the desired ISO
|
||||
|
||||
This goes without saying that you need to have an ISO image file in order to flash it on a USB.
|
||||
|
||||
I am going to use Ubuntu 20.04 ISO (downloadable [here][5]) to test the dd command I showed earlier.
|
||||
|
||||
#### Step 1: Get the USB disk label
|
||||
|
||||
Plug in your USB disk.
|
||||
|
||||
The specific path I entered for `of` was `/dev/sdb`. The USB disks are usually labelled /dev/sdb but that’s not a hard and fast rule.
|
||||
|
||||
This path may differ on your system, but you can confirm the path of the drive with the `lsblk` command. Just look for a listing that looks like the size of your USB drive, and that’ll be it.
|
||||
|
||||
![][6]
|
||||
|
||||
If you are more comfortable with GUI programs, you can also find the drive’s path with tools like GNOME Disks.
|
||||
|
||||
![][7]
|
||||
|
||||
Now that you have established the path to our external drive, let’s create the live USB.
|
||||
|
||||
#### Step 2: Writing the ISO file to the USB disk
|
||||
|
||||
Open up a terminal at the directory where the ISO file is downloaded, and run the following (remember to replace `/dev/sdb` with the name of your storage device if it’s something different):
|
||||
|
||||
```
|
||||
sudo dd if="./ubuntu-20.04.2.0-desktop-amd64.iso" of="/dev/sdb" status="progress" conv="fsync"
|
||||
```
|
||||
|
||||
After that, just let dd do it’s thing, and it’ll print a completion message once it’s done:
|
||||
|
||||
![][8]
|
||||
|
||||
And just like that, you’ve flashed an ISO with dd command in the Linux terminal!
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
Now you’re on your way to doing even more things through the terminal, allowing you to do things faster and quicker than you might have been able to do before.
|
||||
|
||||
Got any remaining questions about the dd command, or something just not working right? Feel free to leave any of it in the comment section below.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/live-usb-with-dd-command/
|
||||
|
||||
作者:[Hunter Wittenborn][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/hunter/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/install-etcher-linux/
|
||||
[2]: https://itsfoss.com/gui-cli-tui/
|
||||
[3]: https://linuxhandbook.com/dd-command/
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/dd-command-for-live-usb-creation.png?resize=800%2C450&ssl=1
|
||||
[5]: https://ubuntu.com/download/desktop/thank-you?version=20.04.2.0&architecture=amd64
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd_disks.png?resize=753%2C264&ssl=1
|
||||
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd_gnome_disks.png?resize=800%2C440&ssl=1
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd-iso-write.png?resize=800%2C322&ssl=1
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://opensource.com/article/21/9/openrit-mystic"
|
||||
[#]: author: "Quinn Foster https://opensource.com/users/quinn-foster"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
@ -1,257 +0,0 @@
|
||||
[#]: subject: "Quadratic algorithms are slow (and hashmaps are fast)"
|
||||
[#]: via: "https://jvns.ca/blog/2021/09/10/hashmaps-make-things-fast/"
|
||||
[#]: author: "Julia Evans https://jvns.ca/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "unigeorge"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Quadratic algorithms are slow (and hashmaps are fast)
|
||||
======
|
||||
|
||||
Hello! I was talking to a friend yesterday who was studying for a programming interview and trying to learn some algorithms basics.
|
||||
|
||||
The topic of quadratic-time vs linear-time algorithms came up, I thought this would be fun to write about here because avoiding quadratic-time algorithms isn’t just important in interviews – it’s sometimes good to know about in real life too! I’ll explain what a “quadratic-time algorithm is” in a minute :)
|
||||
|
||||
here are the 3 things we’ll talk about:
|
||||
|
||||
1. quadratic time functions are WAY WAY WAY slower than linear time functions
|
||||
2. sometimes you can make a quadratic algorithm into a linear algorithm by using a hashmap
|
||||
3. this is because hashmaps lookups are very fast (instant!)
|
||||
|
||||
|
||||
|
||||
I’m going to try to keep the math jargon to a minimum and focus on real code examples and how fast/slow they are.
|
||||
|
||||
### our problem: intersect two lists
|
||||
|
||||
Let’s talk about a simple interview-style problem: getting the intersection of 2 lists of numbers. For example, `intersect([1,2,3], [2,4,5])` should return `[2]`.
|
||||
|
||||
This problem is also somewhat realistic – you could imagine having a real program where you need to take the intersection of 2 lists of IDs.
|
||||
|
||||
### the “obvious” solution:
|
||||
|
||||
Let’s write some code to take the intersection of 2 lists. Here’s a program that does it, called `quadratic.py`.
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
# the actual code
|
||||
def intersection(list1, list2):
|
||||
result = []
|
||||
for x in list1:
|
||||
for y in list2:
|
||||
if x == y:
|
||||
result.append(y)
|
||||
return result
|
||||
|
||||
# some boilerplate so that we can run it from the command line on lists of
|
||||
# different sizes
|
||||
def run(n):
|
||||
# make 2 lists of n+1 elements
|
||||
list1 = list(range(3, n)) + [2]
|
||||
list2 = list(range(n+1, 2*n)) + [2]
|
||||
# intersect them and print out the result
|
||||
print(list(intersection(list1, list2)))
|
||||
|
||||
# Run with the program's first command line argument
|
||||
run(int(sys.argv[1]))
|
||||
```
|
||||
|
||||
The reason it’s called `quadratic.py` is that if `list1` and `list2` have size `n`, then the inner loop (`if x == y`) will run `n^2` times. And in math, functions like `x^2` are called “quadratic” functions.
|
||||
|
||||
### how slow is `quadratic.py`?
|
||||
|
||||
Let’s run this program with a bunch of lists of different lengths. The intersection of the two lists is always the same: `[2]`.
|
||||
|
||||
```
|
||||
$ time python3 quadratic.py 10
|
||||
[2]
|
||||
|
||||
real 0m0.037s
|
||||
$ time python3 quadratic.py 100
|
||||
[2]
|
||||
|
||||
real 0m0.053s
|
||||
$ time python3 quadratic.py 1000
|
||||
[2]
|
||||
|
||||
real 0m0.051s
|
||||
$ time python3 quadratic.py 10000 # 10,000
|
||||
[2]
|
||||
|
||||
real 0m1.661s
|
||||
```
|
||||
|
||||
So far none of this is too bad – it’s still taking less than 2 seconds.
|
||||
|
||||
Then I ran it on two lists with 100,000 elements, and I had to wait a LONG time. Here’s the result:
|
||||
|
||||
```
|
||||
$ time python3 quadratic.py 100000 # 100,000
|
||||
[2]
|
||||
|
||||
real 2m41.059s
|
||||
```
|
||||
|
||||
This is very slow! It’s 160 seconds, which is almost exactly 100x longer than it did to run on 10,000 elements (which was 1.6 seconds). So we can see that after a certain point, every time we make the list 10x bigger, the program takes about 100x longer to run.
|
||||
|
||||
I didn’t try to run this program on 1,000,000 elements, because I knew it would take 100x longer again – probably about 3 hours. I don’t have time for that!
|
||||
|
||||
You can probably see now why quadratic time algorithms can be a problem – even this very simple program starts getting very slow pretty quickly.
|
||||
|
||||
### let’s write a fast version: `linear.py`
|
||||
|
||||
Okay, so let’s write a fast version of the program. First I’ll show you the program, then I’ll explain it.
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
# the actual algorithm
|
||||
def intersection(list1, list2):
|
||||
set1 = set(list1) # this is a hash set
|
||||
result = []
|
||||
for y in list2:
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
return result
|
||||
|
||||
# some boilerplate so that we can run it from the command line on lists of
|
||||
# different sizes
|
||||
def run(n):
|
||||
# make 2 lists of n+1 elements
|
||||
list1 = range(3, n) + [2]
|
||||
list2 = range(n+1, 2*n) + [2]
|
||||
# print out the intersection
|
||||
print(intersection(list1, list2))
|
||||
|
||||
run(int(sys.argv[1]))
|
||||
```
|
||||
|
||||
(this isn’t the most idiomatic Python, but I wanted to write it without using too many python-isms so that people who don’t know Python could understand it more easily)
|
||||
|
||||
We’ve done 2 things differently here than our slow program:
|
||||
|
||||
1. convert `list1` into a set called `set1`
|
||||
2. only use one for loop instead of two for loops
|
||||
|
||||
|
||||
|
||||
### let’s see how fast this `linear.py` program is
|
||||
|
||||
Before we talk about _why_ this program is fast, let’s first prove that it’s fast by running it on some big lists. Here it is running on lists of size 10 to 10,000,000. (remember that our original program started getting SUPER slow when run on 100,000 elements)
|
||||
|
||||
```
|
||||
$ time python3 linear.py 100
|
||||
[2]
|
||||
|
||||
real 0m0.056s
|
||||
$ time python3 linear.py 1000
|
||||
[2]
|
||||
|
||||
real 0m0.036s
|
||||
$ time python3 linear.py 10000 # 10,000
|
||||
[2]
|
||||
|
||||
real 0m0.028s
|
||||
$ time python3 linear.py 100000 # 100,000
|
||||
[2]
|
||||
|
||||
real 0m0.048s <-- quadratic.py took 2 minutes in this case! we're doing it in 0.04 seconds now!!! so fast!
|
||||
$ time python3 linear.py 1000000 # 1,000,000
|
||||
[2]
|
||||
|
||||
real 0m0.178s
|
||||
$ time python3 linear.py 10000000 # 10,000,000
|
||||
[2]
|
||||
|
||||
real 0m1.560s
|
||||
```
|
||||
|
||||
### running `linear.py` on an extremely big list
|
||||
|
||||
If we try to run it on a very very big list (10 billion / 10,000,000,000 elements), then actually we run into a different problem: it’s _fast_ enough (that list is only 100x bigger than the list that took 4.2 seconds, so we could probably do it in 420 seconds), but my computer doesn’t have enough memory to store all of the elements of the list and so the program crashes before it gets there.
|
||||
|
||||
```
|
||||
$ time python3 linear.py 10000000000
|
||||
Traceback (most recent call last):
|
||||
File "/home/bork/work/homepage/linear.py", line 18, in <module>
|
||||
run(int(sys.argv[1]))
|
||||
File "/home/bork/work/homepage/linear.py", line 13, in run
|
||||
list1 = [1] * n + [2]
|
||||
MemoryError
|
||||
|
||||
real 0m0.090s
|
||||
user 0m0.034s
|
||||
sys 0m0.018s
|
||||
```
|
||||
|
||||
We’re not talking about memory usage in this blog post though, so let’s ignore that.
|
||||
|
||||
### okay, why is `linear.py` fast?
|
||||
|
||||
Now I’ll try to explain why `linear.py` is fast.
|
||||
|
||||
Here’s the code again:
|
||||
|
||||
```
|
||||
def intersection(list1, list2):
|
||||
set1 = set(list1) # this is a hash set
|
||||
result = []
|
||||
for y in list2:
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
return result
|
||||
```
|
||||
|
||||
Let’s say that `list1` and `list2` are both lists of about 10,000,000 different elements. That’s kind of a lot of elements!
|
||||
|
||||
So why is this able to run so fast? HASHMAPS!!!
|
||||
|
||||
### hashmap lookups are instant (“constant time”)
|
||||
|
||||
Let’s look at this if statement from our fast program:
|
||||
|
||||
```
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
```
|
||||
|
||||
You might think that this check – `if y in set1` – would be slower if the `set1` contains 10 million elements than it is if `set1` contains 1000 elements. But it’s not! It always takes basically the same amount of time (SUPER FAST), no matter how big `set1` gets.
|
||||
|
||||
This is because `set1` is a hash set, which is a type of hashmap/hashtable which only has keys and no values.
|
||||
|
||||
I’m not going to explain _why_ hashmap lookups are instant in this post, but the amazing Vaidehi Joshi’s [basecs][1] series has explanations of [hash tables][2] and [hash functions][3] which talk about it.
|
||||
|
||||
### accidentally quadratic: real life quadratic algorithms!
|
||||
|
||||
This issue that we saw where quadratic time algorithms are really slow is actually a problem that shows up in real life – Nelson Elhage has a great blog called [accidentally quadratic][4] with stories about performance problems caused by code that accidentally ran in quadratic time.
|
||||
|
||||
### quadratic time algorithms can kind of sneak up on you
|
||||
|
||||
The weird thing about quadratic time algorithms is that when you run them on a small number of elements (like 1000), it doesn’t seem so bad! It’s not that slow! But then if you throw 1,000,000 elements at it, it can really take hours to run.
|
||||
|
||||
So I think it’s worth being broadly aware of them, so you can avoid writing them by accident. Especially if there’s an easy way to write a linear-time algorithm instead (like using a hashmap).
|
||||
|
||||
### hashmaps always feel a little magical to me
|
||||
|
||||
Hashmaps aren’t magic of course (you can learn the math behind why hashmap lookups are instant! it’s cool!), but it always _feels_ a little magical to me, and every time I use hashmaps in a program to speed things up it makes me happy :)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2021/09/10/hashmaps-make-things-fast/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[unigeorge](https://github.com/unigeorge)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://medium.com/basecs
|
||||
[2]: https://medium.com/basecs/taking-hash-tables-off-the-shelf-139cbf4752f0
|
||||
[3]: https://medium.com/basecs/hashing-out-hash-functions-ea5dd8beb4dd
|
||||
[4]: https://accidentallyquadratic.tumblr.com/
|
@ -0,0 +1,327 @@
|
||||
[#]: subject: "How I rediscovered Logo with the Python Turtle module"
|
||||
[#]: via: "https://opensource.com/article/21/9/logo-python-turtle"
|
||||
[#]: author: "Ayush Sharma https://opensource.com/users/ayushsharma"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How I rediscovered Logo with the Python Turtle module
|
||||
======
|
||||
The Logo programming language is available today as a Python package.
|
||||
![Box turtle][1]
|
||||
|
||||
When I was in high school, one of the very first programming languages I was introduced to was Logo. It was interactive and visual. With basic movement commands, you could have your cursor (“turtle”) draw basic shapes and intricate patterns. It was a great way to introduce the compelling concept of an algorithm—a series of instructions for a computer to execute.
|
||||
|
||||
Fortunately, the Logo programming language is available today as a Python package. So let’s jump right in, and you can discover the possibilities with Logo as we go along.
|
||||
|
||||
### Installing the Turtle module
|
||||
|
||||
Logo is available as the [`turtle` package for Python][2]. To use it, you must have Python installed first. Python is already installed on Linux and BSD, and it's easy to install on both [MacOS][3] and [Windows][4].
|
||||
|
||||
Once you have Python installed, install the Turtle module:
|
||||
|
||||
|
||||
```
|
||||
`pip3 install turtle`
|
||||
```
|
||||
|
||||
### Bob draws a square
|
||||
|
||||
With the `turtle` package installed, you can draw some basic shapes.
|
||||
|
||||
To draw a square, imagine a turtle (call him Bob) in the middle of your screen, holding a pen with his tail. Every time Bob moves, he draws a line behind him. How must Bob move to draw a square?
|
||||
|
||||
1. Move forward 100 steps.
|
||||
2. Turn right 90 degrees.
|
||||
3. Move forward 100 steps.
|
||||
4. Turn right 90 degrees.
|
||||
5. Move forward 100 steps.
|
||||
6. Turn right 90 degrees.
|
||||
7. Move forward 100 steps.
|
||||
|
||||
|
||||
|
||||
Now write the above algorithm in Python. Create a file called `logo.py` and place the following code in it.
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! I\'m Bob the turtle!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
bob = turtle.Turtle(shape='turtle')
|
||||
bob.color('orange')
|
||||
|
||||
# Drawing a square
|
||||
bob.forward(100)
|
||||
bob.right(90)
|
||||
bob.forward(100)
|
||||
bob.right(90)
|
||||
bob.forward(100)
|
||||
bob.right(90)
|
||||
bob.forward(100)
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
Save the above as `logo.py` and run it:
|
||||
|
||||
|
||||
```
|
||||
`$ python3 logo.py`
|
||||
```
|
||||
|
||||
Bob draws a square on the screen:
|
||||
|
||||
![Logo drawn square][5]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
### Bob draws a hexagon
|
||||
|
||||
To draw a hexagon, Bob must move like this:
|
||||
|
||||
1. Move forward 150 steps.
|
||||
2. Turn right 60 degrees.
|
||||
3. Move forward 150 steps.
|
||||
4. Turn right 60 degrees.
|
||||
5. Move forward 150 steps.
|
||||
6. Turn right 60 degrees.
|
||||
7. Move forward 150 steps.
|
||||
8. Turn right 60 degrees.
|
||||
9. Move forward 150 steps.
|
||||
10. Turn right 60 degrees.
|
||||
11. Move forward 150 steps.
|
||||
|
||||
|
||||
|
||||
In Python, you can use a [`for` loop][7] to move Bob:
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! I\'m Bob the turtle!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
bob = turtle.Turtle(shape='turtle')
|
||||
bob.color('orange')
|
||||
|
||||
# Drawing a hexagon
|
||||
for i in range(6):
|
||||
|
||||
bob.forward(150)
|
||||
bob.right(60)
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
Run your code again and watch Bob draw a hexagon.
|
||||
|
||||
![Logo drawn hexagon][8]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
### Bob draws a square spiral
|
||||
|
||||
Now try drawing a square spiral, but this time you can speed things up a bit. You can use the `speed` function and set `bob.speed(2000)` so that Bob moves faster.
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! I\'m Bob the turtle!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
bob = turtle.Turtle(shape='turtle')
|
||||
bob.color('orange')
|
||||
|
||||
# Drawing a square spiral
|
||||
bob.speed(2000)
|
||||
for i in range(500):
|
||||
|
||||
bob.forward(i)
|
||||
bob.left(91)
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
![Logo drawn spiral][9]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
### Bob and Larry draw a weird snake thing
|
||||
|
||||
In the above examples, you initialized `Bob` as an object of the `Turtle` class. You're not limited to just one turtle, though. In the next code block, create a second turtle called `Larry` to draw along with Bob.
|
||||
|
||||
The `penup()` function makes the turtles lift their pens, so they don’t draw anything as they move, and the `stamp()` function places a marker whenever it’s called.
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! We\'re Bob and Larry!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
bob = turtle.Turtle(shape='turtle')
|
||||
larry = turtle.Turtle(shape='turtle')
|
||||
bob.color('orange')
|
||||
larry.color('purple')
|
||||
|
||||
bob.penup()
|
||||
larry.penup()
|
||||
bob.goto(-180, 200)
|
||||
larry.goto(-150, 200)
|
||||
for i in range(30, -30, -1):
|
||||
|
||||
bob.stamp()
|
||||
larry.stamp()
|
||||
bob.right(i)
|
||||
larry.right(i)
|
||||
bob.forward(20)
|
||||
larry.forward(20)
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
![Logo drawn snake][10]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
### Bob draws a sunburst
|
||||
|
||||
Bob can also draw simple lines and fill them in with color. The functions `begin_fill()` and `end_fill()` allow Bob to fill a shape with the color set with `fillcolor()`.
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! I\'m Bob the turtle!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
bob = turtle.Turtle(shape='turtle')
|
||||
bob.color('orange')
|
||||
|
||||
# Drawing a filled star thingy
|
||||
bob.speed(2000)
|
||||
bob.fillcolor('yellow')
|
||||
bob.pencolor('red')
|
||||
|
||||
for i in range(200):
|
||||
|
||||
bob.begin_fill()
|
||||
bob.forward(300 - i)
|
||||
bob.left(170)
|
||||
bob.forward(300 - i)
|
||||
bob.end_fill()
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
![Logo drawn sunburst][11]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
### Larry draws a Sierpinski triangle
|
||||
|
||||
Bob enjoys drawing simple geometrical shapes holding a pen with his tail as much as the next turtle, but what he enjoys most is drawing fractals.
|
||||
|
||||
One such shape is the [Sierpinski triangle][12], which is an equilateral triangle recursively subdivided into smaller equilateral triangles. It looks something like this:
|
||||
|
||||
![Logo drawn triangle][13]
|
||||
|
||||
Illustration by Ayush Sharma, [CC BY-SA 4.0][6]
|
||||
|
||||
To draw the Sierpinski triangle above, Bob has to work a bit harder:
|
||||
|
||||
|
||||
```
|
||||
import turtle
|
||||
|
||||
def get_mid_point(point_1: list, point_2: list):
|
||||
|
||||
return ((point_1[0] + point_2[0]) / 2, (point_1[1] + point_2[1]) / 2)
|
||||
|
||||
def triangle(turtle: turtle, points, depth):
|
||||
|
||||
turtle.penup()
|
||||
turtle.goto(points[0][0], points[0][1])
|
||||
|
||||
turtle.pendown()
|
||||
turtle.goto(points[1][0], points[1][1])
|
||||
turtle.goto(points[2][0], points[2][1])
|
||||
turtle.goto(points[0][0], points[0][1])
|
||||
|
||||
if depth > 0:
|
||||
|
||||
triangle(turtle, [points[0], get_mid_point(points[0], points[1]), get_mid_point(points[0], points[2])], depth-1)
|
||||
triangle(turtle, [points[1], get_mid_point(points[0], points[1]), get_mid_point(points[1], points[2])], depth-1)
|
||||
triangle(turtle, [points[2], get_mid_point(points[2], points[1]), get_mid_point(points[0], points[2])], depth-1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
turtle.title('Hi! I\'m Bob the turtle!')
|
||||
turtle.setup(width=800, height=800)
|
||||
|
||||
larry = turtle.Turtle(shape='turtle')
|
||||
larry.color('purple')
|
||||
|
||||
points = [[-175, -125], [0, 175], [175, -125]] # size of triangle
|
||||
|
||||
triangle(larry, points, 5)
|
||||
|
||||
turtle.exitonclick()
|
||||
```
|
||||
|
||||
### Wrap up
|
||||
|
||||
The Logo programming language is a great way to teach basic programming concepts, such as how a computer can execute a set of commands. Also, because the library is now available in Python, it can be used to visualize complex ideas and concepts.
|
||||
|
||||
I hope Bob and Larry have been enjoyable and instructive.
|
||||
|
||||
Have fun, and happy coding.
|
||||
|
||||
* * *
|
||||
|
||||
_This article was originally published on the [author's personal blog][14] and has been adapted with permission._
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/9/logo-python-turtle
|
||||
|
||||
作者:[Ayush Sharma][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ayushsharma
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/patti-black-unsplash.jpg?itok=hS8wQNUg (Box turtle)
|
||||
[2]: https://docs.python.org/3.7/library/turtle.html
|
||||
[3]: https://opensource.com/article/19/5/python-3-default-mac
|
||||
[4]: https://opensource.com/article/19/8/how-install-python-windows
|
||||
[5]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-square.jpg (Logo drawn square)
|
||||
[6]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[7]: https://opensource.com/article/18/3/loop-better-deeper-look-iteration-python
|
||||
[8]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-hexagon.jpg (Logo drawn hexagon)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-square-spiral.jpg (Logo drawn spiral)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-stamping-larry.jpg (Logo drawn snake)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-sunburst.jpg (Logo drawn sunburst)
|
||||
[12]: https://en.wikipedia.org/wiki/Sierpinski_triangle
|
||||
[13]: https://opensource.com/sites/default/files/uploads/rediscovering-logo-python-turtle-sierpinski-triangle.jpg (Logo drawn triangle)
|
||||
[14]: https://notes.ayushsharma.in/2019/06/rediscovering-logo-with-bob-the-turtle
|
@ -0,0 +1,83 @@
|
||||
[#]: subject: "Replace smart quotes with the Linux sed command"
|
||||
[#]: via: "https://opensource.com/article/21/9/sed-replace-smart-quotes"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Replace smart quotes with the Linux sed command
|
||||
======
|
||||
Banish "smart" quotes with your favorite version of sed.
|
||||
![Coding on a computer][1]
|
||||
|
||||
In typography, a pair of quotation marks were traditionally oriented toward one another. They look like this:
|
||||
|
||||
“smart quotes”
|
||||
|
||||
As computers became popular in the mid-twentieth century, the orientation was often abandoned. The original character set of computers didn't have much room to spare, so it makes sense that two double-quotes and two single-quotes were reduced down to just one of each in the ASCII specification. These days the common character set is Unicode, with plenty of space for lots of fancy quotation marks and apostrophes, but many people have become used to the minimalism of just one character for both opening and closing quotes. Besides that, computers actually see the different kinds of quotation marks and apostrophes as distinct characters. In other words, to a copmuter the right double quote is different from the left double quote or a straight quote.
|
||||
|
||||
### Replacing smart quotes with sed
|
||||
|
||||
Computers aren't typewriters. When you press a key on your keyboard, you're not pressing a lever with an inkstamp attached to it. You're just pressing a button that sends a signal to your computer, which the computer interprets as a request to display a specific predefined character. The request depends on your keyboard map. As a Dvorak typist, I've witnessed the confusion on people's faces when they discover "asdf" on my keyboard produces "aoeu" on the screen. You may also have pressed special combinations of keys to produce characters, such as ™ or ß or ≠, that's not even printed on your keyboard.
|
||||
|
||||
Each letter or character, whether it's printed on your keyboard or not, has a code. Character encoding can be expressed in different ways, but to a computer the Unicode sequences u2018 and u2019 produce **‘** and **’**, while the codes u201c and u201d produce the **“** and **”** characters. Knowing these "secret" codes means you can replace them programmatically using a command like [sed][2]. Any version of sed will do, so you can use GNU sed or BSD sed or even [Busybox][3] sed.
|
||||
|
||||
Here's the simple shell script I use:
|
||||
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
# GNU All-Permissive License
|
||||
|
||||
SDQUO=$(echo -ne '\u2018\u2019')
|
||||
RDQUO=$(echo -ne '\u201C\u201D')
|
||||
$SED -i -e "s/[$SDQUO]/\'/g" -e "s/[$RDQUO]/\"/g" "${1}"
|
||||
```
|
||||
|
||||
Save this script as `fixquotes.sh` and then create a separate test file containing smart quotes:
|
||||
|
||||
|
||||
```
|
||||
‘Single quote’
|
||||
“Double quote”
|
||||
```
|
||||
|
||||
Run the script, and then use the [cat][4] command to see the results:
|
||||
|
||||
|
||||
```
|
||||
$ sh ./fixquotes.sh test.txt
|
||||
$ cat test.txt
|
||||
'Single quote'
|
||||
"Double quote"
|
||||
```
|
||||
|
||||
### Install sed
|
||||
|
||||
If you’re using Linux, BSD, or macOS, then you already have GNU or BSD `sed` installed. These are two unique reimplementations of the original `sed` command, and for the script in this article they are functionally the same (that's not true for all scripts, though).
|
||||
|
||||
On Windows, you can [install GNU sed][5] with [Chocolatey][6].
|
||||
|
||||
Vim offers great benefits to writers, regardless of whether they are technically minded or not.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/9/sed-replace-smart-quotes
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl (Coding on a computer)
|
||||
[2]: https://opensource.com/article/20/12/sed
|
||||
[3]: https://opensource.com/article/21/8/what-busybox
|
||||
[4]: https://opensource.com/article/19/2/getting-started-cat-command
|
||||
[5]: https://chocolatey.org/packages/sed
|
||||
[6]: https://opensource.com/article/20/3/chocolatey
|
@ -0,0 +1,136 @@
|
||||
[#]: subject: "Revolt: An Open-Source Alternative to Discord"
|
||||
[#]: via: "https://itsfoss.com/revolt/"
|
||||
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Revolt: An Open-Source Alternative to Discord
|
||||
======
|
||||
|
||||
_**Brief**: Revolt is a promising free and open-source choice to replace Discord. Here, we take a look at what it offers along with its initial impressions._
|
||||
|
||||
Discord is a feature-rich collaboration platform primarily tailored for gamers. Even though you can use Discord on Linux with no issues, it is still a proprietary solution.
|
||||
|
||||
You can choose to use [Element][1] as an open-source solution collaboration platform, but it is not a replacement.
|
||||
|
||||
But, Revolt is an impressive Discord alternative that is open-source.
|
||||
|
||||
Note
|
||||
|
||||
Revolt is in the public beta testing phase and does not offer any mobile applications. It may lack some essential features that you find on Discord.
|
||||
|
||||
Let me highlight what you can expect with Revolt and if it can be a replacement for Discord on Linux.
|
||||
|
||||
### An Open Source Discord Alternative That You Can Self-Host
|
||||
|
||||
![][2]
|
||||
|
||||
Revolt is not just a simple open-source replacement, but you also get the ability to self-host.
|
||||
|
||||
It does lack a variety of features that Discord offers, but you get a lot of basic functionalities to get a head start to start experimenting.
|
||||
|
||||
Even without some features, you could mention it as a feature-rich open-source client. Let us look at the features available right now.
|
||||
|
||||
### Features of Revolt
|
||||
|
||||
![][3]
|
||||
|
||||
While it looks and feels a lot like Discord already, here are some of the key highlights:
|
||||
|
||||
* Ability to create your own server
|
||||
* Create text channels and voice channels
|
||||
* Assign user roles in a server
|
||||
* Tweak the theme (dark/light)
|
||||
* Change the accent color
|
||||
* Manage the font and emoji packs from available options
|
||||
* Custom CSS support
|
||||
* Ability to add bots
|
||||
* Easy to manage permissions for text/voice channels
|
||||
* Send friend requests to other users
|
||||
* Saved notes section
|
||||
* Ability to control notifications
|
||||
* Hardware acceleration support
|
||||
* Dedicated desktop settings
|
||||
* Self-hosting using Docker
|
||||
* User status and custom status support
|
||||
|
||||
|
||||
|
||||
So, as something in the public beta testing phase, it sounds excellent for starters. You already get most of the core functionalities, but you may want to wait to see it as a full-fledged Discord replacement.
|
||||
|
||||
### Initial Impressions of Using Revolt
|
||||
|
||||
![][4]
|
||||
|
||||
If you have used Discord, the user experience will feel familiar. And that is a good thing here.
|
||||
|
||||
For this quick app highlight, I did not compare the resource usage of Discord and Revolt because it is still in beta and won’t be an apples-to-apples comparison.
|
||||
|
||||
However, in my brief testing, it felt snappy, except the case when you load up a text channel for the first time. When publishing this, it did not have the Two-Factor Authentication (2FA) feature but was supposed to be added in their first milestone (Version 1) release.
|
||||
|
||||
![][5]
|
||||
|
||||
Some features like user status, permission management, and appearance tweaks looked useful. But, when it comes to the voice channels, it is not the same way as Discord works, at least for now.
|
||||
|
||||
I have no idea if they plan to do it the same way, but Discord’s voice channel feature is intuitive, fast, and with better controls.
|
||||
|
||||
Not to forget, Discord also offers “Discord Stage,” which is a Clubhouse-like audio room feature.
|
||||
|
||||
Some other features that I couldn’t find included:
|
||||
|
||||
* Ability to react to messages
|
||||
* Noise suppression feature
|
||||
* Change server
|
||||
* Server logs
|
||||
* Variety of useful bots
|
||||
|
||||
|
||||
|
||||
Of course, it will take a significant amount of time to catch up with the features offered by Discord, but at least we now have an open-source solution to Discord.
|
||||
|
||||
You can explore their [project roadmap/release tracker][6] to see what you can expect in its final/future releases.
|
||||
|
||||
### Install Revolt in Linux
|
||||
|
||||
Revolt is available for Linux and Windows. You can choose to use it on your web browser without needing a separate application.
|
||||
|
||||
But, if you need to have it on your desktop, they offer an AppImage file and a deb package that you can grab from its [GitHub releases section][7].
|
||||
|
||||
If you’re new to Linux, refer to our resources on [using an AppImage file][8] and [installing deb packages][9] to get started.
|
||||
|
||||
Feel free to head to its [Feedback section][10] if you want to help them improve with your bug reports and suggestions. Also, you can explore their [GitHub page][11] for more information.
|
||||
|
||||
[Revolt][12]
|
||||
|
||||
What do you think about Revolt? Do you believe that it has the potential to become a good open-source replacement to Discord on Linux?
|
||||
|
||||
Let me know your thoughts in the comments down below!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/revolt/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/element/
|
||||
[2]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/revolt-screenshot.png?resize=800%2C506&ssl=1
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/revolt-desktop-settings.png?resize=800%2C501&ssl=1
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/revolt-screenshot1.png?resize=800%2C509&ssl=1
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/09/revolt-appearance-setting.png?resize=800%2C524&ssl=1
|
||||
[6]: https://github.com/orgs/revoltchat/projects/2
|
||||
[7]: https://github.com/revoltchat/desktop/releases/tag/v1.0.2
|
||||
[8]: https://itsfoss.com/use-appimage-linux/
|
||||
[9]: https://itsfoss.com/install-deb-files-ubuntu/
|
||||
[10]: https://app.revolt.chat/settings/feedback
|
||||
[11]: https://github.com/revoltchat
|
||||
[12]: https://revolt.chat
|
@ -0,0 +1,79 @@
|
||||
[#]: subject: "Adobe Kills Brackets Code Editor & Suggests Using Visual Studio Code"
|
||||
[#]: via: "https://news.itsfoss.com/adobe-kills-brackets-editor/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "wxy"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Adobe 终止支持 Brackets,并建议使用 VS Code 替代
|
||||
======
|
||||
|
||||
> Adobe 结束了对 Brackets 代码编辑器的支持,坚持让用户迁移到微软的 Visual Studio Code。不过,还好总还算是留下了一个复刻。
|
||||
|
||||
![](https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/09/adobe-bracket-visual-studio.jpg?w=1200&ssl=1)
|
||||
|
||||
Brackets 是一个令人印象深刻的现代开源代码编辑器,可用于 Windows、macOS 和 Linux。
|
||||
|
||||
Adobe 以一个社区引导的项目的形式创建了它,来帮助 Web 开发者。我们之前把它列为 [可供编程人员使用的最佳现代文本编辑器][1] 之一。
|
||||
|
||||
不幸的是,Adobe 在 2021 年 9 月 1 日结束了对 Brackets 的支持。
|
||||
|
||||
### 为什么 Adobe 停用了 Brackets?
|
||||
|
||||
![][2]
|
||||
|
||||
看起来可能是 Adobe 与微软的合作关系促使他们拔掉了这个社区项目的插头。
|
||||
|
||||
因此,他们建议用户迁移到微软的 Visual Studio Code 编辑器。
|
||||
|
||||
![][3]
|
||||
|
||||
这是 Brackets 项目中止后 GitHub 的原始页面上的内容。
|
||||
|
||||
### Visual Studio Code 作为 Brackets 的替代品
|
||||
|
||||
当然,微软的 Visual Studio Code 是一个很好的替代品,而且建立在开源的基础上。然而,当你从他们的网站上下载 Visual Studio Code 时,它并不在一个促进自由和开源软件的许可证之下。
|
||||
|
||||
因此,你可能不得不从源代码构建,或者尝试 [VSCodium][4],这是一个没有遥测/跟踪功能的 Visual Studio Code 的自由许可版本。
|
||||
|
||||
另外,有一个 [关于从 Brackets 迁移的官方指南][5],如果你感兴趣,可以去看看。
|
||||
|
||||
### Brackets 将继续以没有 Adobe 的复刻出现
|
||||
|
||||
![][6]
|
||||
|
||||
尽管 Adobe 已经停止了这个项目,但 [原网站][7] 仍然存在,以维持这个项目的复刻。
|
||||
|
||||
该项目名称可能会改变,但从目前来看,它叫 “Brackets Continued”,以帮助用户识别该复刻。
|
||||
|
||||
请注意,这个复刻项目还没有发布,我们也不知道它是否会作为一个独立的项目继续下去。
|
||||
|
||||
所以,如果你想帮助 Brackets 复刻,并以某种方式帮助维护它,请前往其 GitHub 页面了解更多细节。
|
||||
|
||||
- [Brackets Continued(复刻)][8]
|
||||
|
||||
你喜欢用什么作为你的代码编辑器?你喜欢用 Brackets 代码编辑器进行 Web 开发工作吗?欢迎在评论中分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/adobe-kills-brackets-editor/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
|
||||
[2]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/09/brackets-screenshot.png?w=800&ssl=1
|
||||
[3]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/09/adobe-brackets-github.png?w=964&ssl=1
|
||||
[4]: https://vscodium.com
|
||||
[5]: https://code.visualstudio.com/migrate-from-brackets
|
||||
[6]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/09/brackets-fork.png?w=1511&ssl=1
|
||||
[7]: https://brackets.io
|
||||
[8]: https://github.com/brackets-cont/brackets
|
@ -7,67 +7,67 @@
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Debug a web page error from the command line
|
||||
从命令行调试网页错误
|
||||
======
|
||||
One way to debug a web server is by using the wget command-line program.
|
||||
调试网络服务器的一种方法是使用 wget 命令行程序。
|
||||
![Digital creative of a browser on the internet][1]
|
||||
|
||||
Sometimes when managing a website, things can get messed up. You might remove some stale content and replace it with a redirect to other pages. Later, after making other changes, you find some web pages become entirely inaccessible. You might see an error in your browser that "The page isn't redirecting properly" with a suggestion to check your cookies.
|
||||
有时在管理一个网站时,事情会被搞得一团糟。你可能会删除一些陈旧的内容,用重定向到其他页面来代替。后来,在做了其他改动后,你发现一些网页变得完全无法访问了。你可能会在浏览器中看到一个错误:“该页面没有正确重定向”,并建议你检查你的 cookies。
|
||||
|
||||
![Redirect loop example in Firefox][2]
|
||||
|
||||
Screenshot by Jim Hall, [CC-BY SA 4.0][3]
|
||||
Screenshot by Jim Hall,[CC-BY SA 4.0][3]
|
||||
|
||||
One way to debug this situation is by using the `wget` command-line program, with the `-S` option to show all server responses. When using `wget` for debugging, I also prefer to save the output to some temporary file, using the `-O` option, in case I need to view its contents later.
|
||||
调试这种情况的一个方法是使用 `wget` 命令行程序,使用 `-S` 选项来显示所有的服务器响应。当使用 `wget` 进行调试时,我也喜欢使用 `-O` 选项将输出保存到一些临时文件中,以备以后需要查看其内容。
|
||||
|
||||
|
||||
```
|
||||
$ wget -O /tmp/test.html -S <http://10.0.0.11/announce/>
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/announce/>
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/announce/>
|
||||
Connecting to 10.0.0.11:80... connected.
|
||||
HTTP request sent, awaiting response...
|
||||
|
||||
HTTP request sent, awaiting response...
|
||||
|
||||
HTTP/1.1 302 Found
|
||||
|
||||
|
||||
Date: Tue, 24 Aug 2021 22:09:49 GMT
|
||||
|
||||
|
||||
Server: Apache/2.4.48 (Fedora)
|
||||
|
||||
|
||||
X-Powered-By: PHP/7.4.21
|
||||
|
||||
|
||||
Location: <http://10.0.0.11/assets/>
|
||||
|
||||
|
||||
Content-Length: 0
|
||||
|
||||
|
||||
Keep-Alive: timeout=5, max=100
|
||||
|
||||
|
||||
Connection: Keep-Alive
|
||||
|
||||
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Location: <http://10.0.0.11/assets/> [following]
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/assets/>
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/assets/>
|
||||
Reusing existing connection to 10.0.0.11:80.
|
||||
HTTP request sent, awaiting response...
|
||||
|
||||
HTTP request sent, awaiting response...
|
||||
|
||||
HTTP/1.1 302 Found
|
||||
|
||||
|
||||
Date: Tue, 24 Aug 2021 22:09:49 GMT
|
||||
|
||||
|
||||
Server: Apache/2.4.48 (Fedora)
|
||||
|
||||
|
||||
X-Powered-By: PHP/7.4.21
|
||||
|
||||
|
||||
Location: <http://10.0.0.11/announce/>
|
||||
|
||||
|
||||
Content-Length: 0
|
||||
|
||||
|
||||
Keep-Alive: timeout=5, max=99
|
||||
|
||||
|
||||
Connection: Keep-Alive
|
||||
|
||||
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Location: <http://10.0.0.11/announce/> [following]
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/announce/>
|
||||
\--2021-08-24 17:09:49-- <http://10.0.0.11/announce/>
|
||||
Reusing existing connection to 10.0.0.11:80.
|
||||
.
|
||||
.
|
||||
@ -75,7 +75,7 @@ Reusing existing connection to 10.0.0.11:80.
|
||||
20 redirections exceeded.
|
||||
```
|
||||
|
||||
I've omitted a lot of repetition in this output. By reading the server responses, you can see that `http ://10.0.0.11/announce/` redirects immediately to `http ://10.0.0.11/assets/`, which then redirects back to `http ://10.0.0.11/announce/`. And so on. This is an endless loop and `wget` will exit after 20 redirections. But armed with this debugging information, you can fix the redirects and avoid the loop.
|
||||
我在这个输出中省略了很多重复的内容。通过阅读服务器的响应,你可以看到 `http://10.0.0.11/announce/` 立即重定向到 `http://10.0.0.11/assets/`,然后又重定向到 `http://10.0.0.11/announce/`。以此类推。这是一个无休止的循环,`wget` 将在 20 次重定向后退出。但有了这些调试信息,你可以修复重定向,避免循环。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -83,7 +83,7 @@ via: https://opensource.com/article/21/9/wget-debug-web-server
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
@ -92,4 +92,4 @@ via: https://opensource.com/article/21/9/wget-debug-web-server
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/firefox-redirect-loop.png (Redirect loop example in Firefox)
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
116
translated/tech/20210908 How to Run Java Programs in Ubuntu.md
Normal file
116
translated/tech/20210908 How to Run Java Programs in Ubuntu.md
Normal file
@ -0,0 +1,116 @@
|
||||
[#]: subject: "How to Run Java Programs in Ubuntu"
|
||||
[#]: via: "https://itsfoss.com/run-java-program-ubuntu/"
|
||||
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
如何在 Ubuntu 中运行 Java 程序
|
||||
======
|
||||
|
||||
那么,你已经开始学习 Java 编程了?这很好。
|
||||
|
||||
你想在你的 Linux 系统上运行 Java 程序?那就更好了。
|
||||
|
||||
让我告诉你如何在 Ubuntu 和其他 Linux 发行版的终端中运行 Java。
|
||||
|
||||
### 在 Ubuntu 中运行 Java 程序
|
||||
|
||||
让我们在这里按正确的步骤进行。
|
||||
|
||||
#### 第一步:安装 Java 编译器
|
||||
|
||||
要运行一个 Java 程序,你需要先编译该程序。为此你需要 Java 编译器。
|
||||
|
||||
Java 编译器是 [JDK][1](Java 开发工具包)的一部分。你需要安装 JDK,以便编译和运行 Java 程序。
|
||||
|
||||
首先,检查你的系统上是否已经安装了 Java 编译器:
|
||||
|
||||
```
|
||||
javac --version
|
||||
```
|
||||
|
||||
如果你看到类似 “Command ‘javac’ not found, but can be installed with” 的错误,这意味着你需要安装 Java 开发工具包。
|
||||
|
||||
![Check if Java compiler is already installed or not][2]
|
||||
|
||||
在 Ubuntu 上安装 JDK 的最简单方法是使用 Ubuntu 的默认包:
|
||||
|
||||
```
|
||||
sudo apt install default-jdk
|
||||
```
|
||||
|
||||
你会被要求输入你的账户密码。当你输入密码时,屏幕上什么也看不到。这很正常。直接输入密码即可。当询问时,按回车键或 Y 键。
|
||||
|
||||
![Installing JDK that also contains the Java compiler][3]
|
||||
|
||||
上述命令应该适用于其他基于 Debian 和 Ubuntu 的发行版,如 Linux Mint、Elementary OS 等。对于其他发行版,请使用你的发行版的包管理器。包的名称也可能不同。
|
||||
|
||||
安装完毕后,验证 javac 现在是否可用。
|
||||
|
||||
![Verify that Java compiler can be used now][4]
|
||||
|
||||
#### 第二步:在 Linux 中编译 Java 程序
|
||||
|
||||
因为这个原因,你需要有一个 Java 程序文件。假设你创建了一个名为 **HelloWorld.java** 的新的 Java 程序文件,它的内容如下:
|
||||
|
||||
```
|
||||
class HelloWorld{
|
||||
public static void main(String args[]){
|
||||
System.out.println("Hello World");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你可以[使用终端的 Nano 编辑器][5]或 Gedit 图形化文本编辑器来编写你的 Java 程序。
|
||||
|
||||
```
|
||||
javac HelloWorld.java
|
||||
```
|
||||
|
||||
如果没有错误,上面的命令不会产生输出。
|
||||
|
||||
当你编译 Java 程序时,它会生成一个 .class 文件,文件名是你在程序中使用的类。你需要运行这个类文件。
|
||||
|
||||
#### 第三步:运行 Java 类文件
|
||||
|
||||
你不需要在这里指定类的扩展名。只需要类的名称。而这一次,你使用 java 命令,而不是 javac。
|
||||
|
||||
```
|
||||
java HelloWorld
|
||||
```
|
||||
|
||||
我的程序将在屏幕上打印 Hello World。
|
||||
|
||||
![Running java programs in the Linux terminal][6]
|
||||
|
||||
这就是你如何在 Linux 终端中运行一个 Java 程序。
|
||||
|
||||
这是最简单的一个例子。这个示例程序只有一个类。Java 编译器为你程序中的每个类都创建一个类文件。对于较大的程序和项目来说,事情会变得很复杂。
|
||||
|
||||
这就是为什么我建议[在 Ubuntu 上安装 Eclipse][7]来进行 Java 编程。在 IDE 中编程更容易。
|
||||
|
||||
希望本教程对你有所帮助。有问题或建议吗?评论区都是你的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/run-java-program-ubuntu/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://jdk.java.net/
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/java-compiler-check-ubuntu.png?resize=800%2C328&ssl=1
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/09/install-jdk-ubuntu.png?resize=800%2C430&ssl=1
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/java-compiler-ubuntu.png?resize=798%2C226&ssl=1
|
||||
[5]: https://itsfoss.com/nano-editor-guide/
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/09/running-java-programs-in-Linux-terminal.png?resize=798%2C301&ssl=1
|
||||
[7]: https://itsfoss.com/install-latest-eclipse-ubuntu/
|
@ -0,0 +1,126 @@
|
||||
[#]: subject: "How to Use the dd Command to Create a Live USB Drive in Linux Terminal [For Experts and Adventurers]"
|
||||
[#]: via: "https://itsfoss.com/live-usb-with-dd-command/"
|
||||
[#]: author: "Hunter Wittenborn https://itsfoss.com/author/hunter/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "perfiffer"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
怎样在 Linux 终端下使用 dd 命令创建一个 Live USB 驱动器 [针对专家和冒险者]
|
||||
======
|
||||
|
||||
有很多的图形化工具可以用来创建 live USB 驱动器。Linux 上的 [Etcher][1] 可能是最受欢迎的。为此,Ubuntu 开发了自己的启动盘创建工具。
|
||||
|
||||
但是,高级 Linux 用户可能更喜欢使用 dd 命令在 Linux 终端中创建 live USB,这会更快速便捷。
|
||||
|
||||
dd 命令是一个 [客户端][2] 工具,提供了强大的功能用来复制和转换文件。
|
||||
|
||||
一个普通的使用示例,用户使用 dd 命令向他们的外部存储设备(例如 USB 驱动盘)写入 ISO 文件,用来给他们的电脑或者笔记本安装一个 Linux 发型版。
|
||||
|
||||
这就是我将在本教程中展示的内容。我将带你认识需要的命令,从终端找到我们的 USB 驱动器,然后对 ISO 文件进行实际刷写。
|
||||
|
||||
### 使用 dd 命令从 ISO 镜像创建 live USB
|
||||
|
||||
在我向你展示步骤前,让我带你快速过一下你将要使用到的命令并解释它的作用。
|
||||
|
||||
这是一个使用命令刷写 ISO 的例子:
|
||||
|
||||
```
|
||||
dd if="./filename.iso" of="/dev/sdb" status="progress" conv="fsync"
|
||||
```
|
||||
|
||||
让我们来看看 [dd 命令][3] 实际都做了些什么。
|
||||
|
||||
#### 理解 dd 命令
|
||||
|
||||
![Explanation of the dd command for live USB creation][4]
|
||||
|
||||
首先,你输入 `dd`。没错,这就是你要运行的程序的名称。
|
||||
|
||||
接下来,你指定 `if="./filename.iso"`。`if` 代表 input file,告诉 `dd` 命令你将要向外部存储设备写入哪个文件。
|
||||
|
||||
之后,你输入 `of="/dev/sdb"`。和 `if` 一样,`of` 代表的是 output file。
|
||||
|
||||
要记住的是,输出文件在技术上不必是系统上的文件。你还可以指定诸如外部设备路径之类的内容(如示例所示),它看起来像系统上的普通文件,但实际上指向连接到你机器的设备。
|
||||
|
||||
`status` 可以设定为 3 个选项:`none`、`noxfer` 和 `progress`。
|
||||
|
||||
你设置的 `progress` 选项将使 `dd` 任务显示有关已将多少 ISO 文件传输到存储驱动器的定期统计信息,以及对 `dd` 任务完成前需要多长时间的估计。
|
||||
|
||||
如果你改为设置 `none` 选项,`dd` 任务只会在写入 ISO 文件期间打印错误消息,并且删除进度条之类的内容。
|
||||
|
||||
`noxfer` 选项隐藏了传输完成后打印的一些信息,例如从开始到完成所用的时间。
|
||||
|
||||
最后,你将 `conv` 选项设置为 `fsync`。这会导致 `dd` 任务在整个 ISO 文件写入 USB 驱动器之前不会报告成功写入。
|
||||
|
||||
如果你省略这个选项,`dd` 任务会工作的很好(并且实际上可能看起来运行得更快),但你可能会发现你的系统需要很长时间才能告诉你移除 USB 驱动器是安全的,因为它会在后台完成 ISO 的内容写入,从而允许你在此期间做其它事情。
|
||||
|
||||
现在你明白了你必须做什么,让我们看看如何去做。
|
||||
|
||||
注意事项
|
||||
|
||||
命令行是把双刃剑。当你在命令行使用类似于 `dd` 命令时必须十分小心。你必须确保你输入文件写入的地方是正确的设备。一个错误的步骤就可能会格式化你的系统硬盘,你的操作系统也会因此而损坏。
|
||||
|
||||
#### 第一步: 下载所需的 ISO 镜像
|
||||
|
||||
不用说,你需要有一个 ISO 镜像文件才能将其刷写到 USB 上。
|
||||
|
||||
我将使用 Ubuntu 20.04 ISO (可在此处下载[5]) 来测试我之前介绍的 `dd` 命令。
|
||||
|
||||
#### 第二步: 获取 USB 盘符
|
||||
|
||||
插入你的 USB 磁盘
|
||||
|
||||
我为 `of` 参数输入的具体路径是 `/dev/sdb`。USB 磁盘通常会标记为 /dev/sdb,但这不是硬性规定。
|
||||
|
||||
此路径可能因你的系统而异,你可以使用 `lsblk` 命令确认 USB 磁盘的路径。只需从列表中查找一个看起来像你的 USB 磁盘大小的驱动器,就可以了。
|
||||
|
||||
![][6]
|
||||
|
||||
如果你更熟悉 GUI 程序,还可以使用 GNOME Disks 等工具找到驱动器的路径。
|
||||
|
||||
![][7]
|
||||
|
||||
现在你已经确认了外部驱动器的路径,让我们开始创建 live USB。
|
||||
|
||||
#### 第三步:将 ISO 文件写入 USB 磁盘
|
||||
|
||||
在下载 ISO 文件的目录打开一个终端,然后运行以下命令(如果 `/dev/sdb` 与你的存储设备名称不同,请记住将其替换):
|
||||
|
||||
```
|
||||
sudo dd if="./ubuntu-20.04.2.0-desktop-amd64.iso" of="/dev/sdb" status="progress" conv="fsync"
|
||||
```
|
||||
之后,让 `dd` 去做剩下的事情,它会在完成后打印一条完成消息:
|
||||
|
||||
![][8]
|
||||
|
||||
就像这样,你已经在 Linux 终端中使用 `dd` 命令刷写了 ISO 文件!
|
||||
|
||||
### 总结
|
||||
|
||||
现在,你可以通过终端做更多的事情,让你的工作效率大大提高。
|
||||
|
||||
对 `dd` 命令有任何剩余的问题,或者无法正常工作?请随时在下面的评论部分中留下你的问题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/live-usb-with-dd-command/
|
||||
|
||||
作者:[Hunter Wittenborn][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[perfiffer](https://github.com/perfiffer)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/hunter/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/install-etcher-linux/
|
||||
[2]: https://itsfoss.com/gui-cli-tui/
|
||||
[3]: https://linuxhandbook.com/dd-command/
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/dd-command-for-live-usb-creation.png?resize=800%2C450&ssl=1
|
||||
[5]: https://ubuntu.com/download/desktop/thank-you?version=20.04.2.0&architecture=amd64
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd_disks.png?resize=753%2C264&ssl=1
|
||||
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd_gnome_disks.png?resize=800%2C440&ssl=1
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/08/dd-iso-write.png?resize=800%2C322&ssl=1
|
@ -0,0 +1,251 @@
|
||||
[#]: subject: "Quadratic algorithms are slow (and hashmaps are fast)"
|
||||
[#]: via: "https://jvns.ca/blog/2021/09/10/hashmaps-make-things-fast/"
|
||||
[#]: author: "Julia Evans https://jvns.ca/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "unigeorge"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
浅谈慢速的二次算法与快速的 hashmap
|
||||
======
|
||||
|
||||
大家好!昨天我与一位正在准备编程面试并努力学习算法基础知识的朋友进行了一些交流。
|
||||
|
||||
我们聊到了二次时间与线性时间算法的话题,我认为在这里写这篇文章会很有趣,因为避免二次时间算法不仅在面试中很重要——有时在现实生活中了解一下也是很好的!后面我会快速解释一下什么是“二次时间算法” :)
|
||||
|
||||
以下是我们将要讨论的 3 件事:
|
||||
|
||||
1. 二次时间函数比线性时间函数慢得非常非常多
|
||||
2. 有时可以通过使用 hashmap 把二次算法变成线性算法
|
||||
3. 这是因为 hashmap 查找非常快(即时查询!)
|
||||
|
||||
我会尽量避免使用数学术语,重点关注真实的代码示例以及它们到底有多快/多慢。
|
||||
|
||||
### 目标问题:取两个列表的交集
|
||||
|
||||
我们来讨论一个简单的面试式问题:获取 2 个数字列表的交集。 例如,`intersect([1,2,3], [2,4,5])` 应该返回 `[2]`。
|
||||
|
||||
这个问题也是有些现实应用的——你可以假设有一个真实程序,其需求正是取两个 ID 列表交集。
|
||||
|
||||
### “显而易见”的解决方案:
|
||||
|
||||
我们来写一些获取 2 个列表交集的代码。下面是一个实现此需求的程序,命名为“quadratic.py”。
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
# 实际运行的代码
|
||||
def intersection(list1, list2):
|
||||
result = []
|
||||
for x in list1:
|
||||
for y in list2:
|
||||
if x == y:
|
||||
result.append(y)
|
||||
return result
|
||||
|
||||
# 一些样板,便于我们从命令行运行程序,处理不同大小的列表
|
||||
def run(n):
|
||||
# 定义两个有 n+1 个元素的列表
|
||||
list1 = list(range(3, n)) + [2]
|
||||
list2 = list(range(n+1, 2*n)) + [2]
|
||||
# 取其交集并输出结果
|
||||
print(list(intersection(list1, list2)))
|
||||
|
||||
# 使用第一个命令行参数作为输入,运行程序
|
||||
run(int(sys.argv[1]))
|
||||
```
|
||||
|
||||
程序名为 `quadratic.py`(LCTT 译注:“quadratic”意为“二次的”)的原因是:如果 `list1` 和 `list2` 的大小为 `n`,那么内层循环(`if x == y`)会运行 `n^2` 次。在数学中,像 `x^2` 这样的函数就称为“二次”函数。
|
||||
|
||||
### `quadratic.py` 有多慢?
|
||||
|
||||
用一些不同长度的列表来运行这个程序,两个列表的交集总是相同的:`[2]`。
|
||||
|
||||
```
|
||||
$ time python3 quadratic.py 10
|
||||
[2]
|
||||
|
||||
real 0m0.037s
|
||||
$ time python3 quadratic.py 100
|
||||
[2]
|
||||
|
||||
real 0m0.053s
|
||||
$ time python3 quadratic.py 1000
|
||||
[2]
|
||||
|
||||
real 0m0.051s
|
||||
$ time python3 quadratic.py 10000 # 10,000
|
||||
[2]
|
||||
|
||||
real 0m1.661s
|
||||
```
|
||||
|
||||
到目前为止,一切都还不错——程序仍然只花费不到 2 秒的时间。
|
||||
|
||||
然后运行该程序处理两个包含 100,000 个元素的列表,我不得不等待了很长时间。结果如下:
|
||||
|
||||
```
|
||||
$ time python3 quadratic.py 100000 # 100,000
|
||||
[2]
|
||||
|
||||
real 2m41.059s
|
||||
```
|
||||
|
||||
这可以说相当慢了!总共花费了 160 秒,几乎是在 10,000 个元素上运行时(1.6 秒)的 100 倍。所以我们可以看到,在某个点之后,每次我们将列表扩大 10 倍,程序运行的时间就会增加大约 100 倍。
|
||||
|
||||
我没有尝试在 1,000,000 个元素上运行这个程序,因为我知道它会花费又 100 倍的时间——可能大约需要 3 个小时。我没时间这样做!
|
||||
|
||||
你现在大概明白了为什么二次时间算法会成为一个问题——即使是这个非常简单的程序也会很快变得非常缓慢。
|
||||
|
||||
### 快速版:`linear.py`
|
||||
|
||||
好,接下来我们编写一个快速版的程序。我先给你看看程序的样子,然后再分析。
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
# 实际执行的算法
|
||||
def intersection(list1, list2):
|
||||
set1 = set(list1) # this is a hash set
|
||||
result = []
|
||||
for y in list2:
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
return result
|
||||
|
||||
# 一些样板,便于我们从命令行运行程序,处理不同大小的列表
|
||||
def run(n):
|
||||
# 定义两个有 n+1 个元素的列表
|
||||
list1 = range(3, n) + [2]
|
||||
list2 = range(n+1, 2*n) + [2]
|
||||
# 输出交集结果
|
||||
print(intersection(list1, list2))
|
||||
|
||||
run(int(sys.argv[1]))
|
||||
```
|
||||
|
||||
(这不是最惯用的 Python 使用方式,但我想在尽量避免使用太多 Python 思想的前提下编写代码,以便不了解 Python 的人能够更容易理解)
|
||||
|
||||
这里我们做了两件与慢速版程序不同的事:
|
||||
|
||||
1. 将 `list1` 转换成名为 `set1` 的 set 集合
|
||||
2. 只使用一个 for 循环而不是两个
|
||||
|
||||
### 看看 `linear.py` 程序有多快
|
||||
|
||||
在讨论 _为什么_ 这个程序快之前,我们先在一些大型列表上运行该程序,以此证明它确实是很快的。此处演示该程序依次在大小为 10 到 10,000,000 的列表上运行的过程。(请记住,我们上一个的程序在 100,000 个元素上运行时开始变得非常非常慢)
|
||||
|
||||
```
|
||||
$ time python3 linear.py 100
|
||||
[2]
|
||||
|
||||
real 0m0.056s
|
||||
$ time python3 linear.py 1000
|
||||
[2]
|
||||
|
||||
real 0m0.036s
|
||||
$ time python3 linear.py 10000 # 10,000
|
||||
[2]
|
||||
|
||||
real 0m0.028s
|
||||
$ time python3 linear.py 100000 # 100,000
|
||||
[2]
|
||||
|
||||
real 0m0.048s <-- quadratic.py took 2 minutes in this case! we're doing it in 0.04 seconds now!!! so fast!
|
||||
$ time python3 linear.py 1000000 # 1,000,000
|
||||
[2]
|
||||
|
||||
real 0m0.178s
|
||||
$ time python3 linear.py 10000000 # 10,000,000
|
||||
[2]
|
||||
|
||||
real 0m1.560s
|
||||
```
|
||||
|
||||
### 在极大型列表上运行 `linear.py`
|
||||
|
||||
如果我们试着在一个非常非常大的列表(100 亿 / 10,000,000,000 个元素)上运行它,那么实际上会遇到另一个问题:它足够 _快_ 了(该列表仅比花费 4.2 秒的列表大 100 倍,因此我们大概应该能在不超过 420 秒的时间内完成),但我的计算机没有足够的内存来存储列表的所有元素,因此程序在运行结束之前崩溃了。
|
||||
|
||||
```
|
||||
$ time python3 linear.py 10000000000
|
||||
Traceback (most recent call last):
|
||||
File "/home/bork/work/homepage/linear.py", line 18, in <module>
|
||||
run(int(sys.argv[1]))
|
||||
File "/home/bork/work/homepage/linear.py", line 13, in run
|
||||
list1 = [1] * n + [2]
|
||||
MemoryError
|
||||
|
||||
real 0m0.090s
|
||||
user 0m0.034s
|
||||
sys 0m0.018s
|
||||
```
|
||||
|
||||
不过本文不讨论内存使用,所以我们可以忽略这个问题。
|
||||
|
||||
### 那么,为什么 `linear.py` 很快呢?
|
||||
|
||||
现在我将试着解释为什么 `linear.py` 很快。
|
||||
|
||||
再看一下我们的代码:
|
||||
|
||||
```
|
||||
def intersection(list1, list2):
|
||||
set1 = set(list1) # this is a hash set
|
||||
result = []
|
||||
for y in list2:
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
return result
|
||||
```
|
||||
|
||||
假设 `list1` 和 `list2` 都是大约 10,000,000 个不同元素的列表,这样的元素数量可以说是很大了!
|
||||
|
||||
那么为什么它还能够运行得如此之快呢?因为 hashmap!!!
|
||||
|
||||
### hashmap 查找是即时的(“常数级时间”)
|
||||
|
||||
我们看一下快速版程序中的 if 语句:
|
||||
|
||||
```
|
||||
if y in set1:
|
||||
result.append(y)
|
||||
```
|
||||
|
||||
你可能会认为如果 `set1` 包含 1000 万个元素,那么这个查找——`if y in set1` 会比 `set1` 包含 1000 个元素时慢。但事实并非如此!无论 `set1` 有多大,所需时间基本是相同的(超级快)。
|
||||
|
||||
这是因为 `set1` 是一个 hash set 集合,它是一种只有键没有值的 hashmap 或 hashtable 结构。
|
||||
|
||||
我不准备在本文中解释 _为什么_ hashmap 查找是即时的,但是神奇的 Vaidehi Joshi 的 [basecs][1] 系列中有关于 [hash table][2] 和 [hash 函数][3] 的解释,其中讨论了 hashmap 即时查找的原因。
|
||||
|
||||
### 不经意的二次方:现实中的二次算法!
|
||||
|
||||
二次时间算法真的很慢,我们看到的的这个问题实际上在现实中也会遇到——Nelson Elhage 有一个很棒的博客,名为 [不经意的二次方][4],其中有关于不经意以二次时间算法运行代码导致性能问题的故事。
|
||||
|
||||
### 二次时间算法可能会“偷袭”你
|
||||
|
||||
关于二次时间算法的奇怪之处在于,当你在少量元素(如 1000)上运行它们时,它看起来并没有那么糟糕!没那么慢!但是如果你给它 1,000,000 个元素,它真的会花费几个小时去运行。
|
||||
|
||||
所以我认为它还是值得深入了解的,这样你就可以避免无意中使用二次时间算法,特别是当有一种简单的方法来编写线性时间算法(例如使用 hashmap)时。
|
||||
|
||||
### 总是让我感到一丝神奇的 hashmap
|
||||
|
||||
hashmap 当然不是魔法(你可以学习一下为什么 hashmap 查找是即时的!真的很酷!),但它总是让人 _感觉_ 有点神奇,每次我在程序中使用 hashmap 来加速,都会使我感到开心 :)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2021/09/10/hashmaps-make-things-fast/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[unigeorge](https://github.com/unigeorge)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://medium.com/basecs
|
||||
[2]: https://medium.com/basecs/taking-hash-tables-off-the-shelf-139cbf4752f0
|
||||
[3]: https://medium.com/basecs/hashing-out-hash-functions-ea5dd8beb4dd
|
||||
[4]: https://accidentallyquadratic.tumblr.com/
|
Loading…
Reference in New Issue
Block a user